> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Job debugging

> Diagnose failed Livepeer AI and video jobs: error patterns by HTTP status, cold model timeouts, validation errors, and the network-direct troubleshooting flow.

export const CenteredContainer = ({children, maxWidth = "800px", padding = "0", preset = "default", width = "", minWidth = "", marginRight = "", marginBottom = "", textAlign = "", style = {}, className = "", ...rest}) => {
  const presets = {
    default: {},
    fitContent: {
      width: "fit-content",
      minWidth: "fit-content"
    },
    readable70: {
      width: "70%",
      minWidth: "fit-content"
    },
    readable80: {
      width: "80%",
      minWidth: "fit-content"
    },
    readable90: {
      width: "90%"
    },
    wide900: {
      maxWidth: "900px"
    }
  };
  const presetStyle = presets[preset] || presets.default;
  return <div className={className} style={{
    maxWidth: presetStyle.maxWidth || maxWidth,
    margin: "0 auto",
    padding: padding,
    ...presetStyle.width ? {
      width: presetStyle.width
    } : {},
    ...presetStyle.minWidth ? {
      minWidth: presetStyle.minWidth
    } : {},
    ...width ? {
      width
    } : {},
    ...minWidth ? {
      minWidth
    } : {},
    ...marginRight ? {
      marginRight
    } : {},
    ...marginBottom ? {
      marginBottom
    } : {},
    ...textAlign ? {
      textAlign
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

export const TableCell = ({children, align = "left", header = false, style = {}, className = "", ...rest}) => {
  const Component = header ? "th" : "td";
  return <Component className={className} style={{
    padding: "0.75rem 1rem",
    textAlign: align,
    border: header ? "none" : "1px solid var(--lp-color-border-default)",
    ...style
  }} {...rest}>
      {children}
    </Component>;
};

export const TableRow = ({children, header = false, hover = false, style = {}, className = "", ...rest}) => {
  const rowId = `table-row-${Math.random().toString(36).substr(2, 9)}`;
  return <>
      {hover && <style>{`
          #${rowId}:hover {
            background-color: var(--lp-color-bg-card);
          }
        `}</style>}
      <tr id={rowId} className={className} style={{
    ...header && ({
      backgroundColor: "var(--lp-color-accent-strong)",
      color: "var(--lp-color-on-accent)",
      fontWeight: "bold"
    }),
    ...style
  }} {...rest}>
        {children}
      </tr>
    </>;
};

export const StyledTable = ({children, variant = "default", style = {}, className = "", ...rest}) => {
  const wrapperVariants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)",
      overflow: "hidden"
    },
    bordered: {
      border: "2px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-page)",
      overflow: "hidden"
    },
    minimal: {
      border: "none",
      backgroundColor: "transparent",
      overflow: "visible"
    }
  };
  return <div data-docs-styled-table-shell className={className} style={{
    width: "100%",
    padding: 0,
    margin: 0,
    ...wrapperVariants[variant],
    ...style
  }} {...rest}>
      <table data-docs-styled-table style={{
    width: "100%",
    borderCollapse: "collapse",
    borderSpacing: 0,
    margin: 0,
    backgroundColor: "transparent"
  }}>
        {children}
      </table>
    </div>;
};

<CenteredContainer preset="readable90">
  <Tip>Most job failures are one of three things: authentication (fix immediately), validation (fix the request body), or cold model delay (wait and retry). Check the HTTP status code first.</Tip>
</CenteredContainer>

<CustomDivider />

<CustomDivider />

## Errors by HTTP status code

<StyledTable variant="bordered">
  <thead>
    <TableRow header>
      <TableCell header>Status</TableCell>
      <TableCell header>Cause</TableCell>
      <TableCell header>Fix</TableCell>
    </TableRow>
  </thead>

  <tbody>
    <TableRow>
      <TableCell>**401**</TableCell>
      <TableCell>Invalid, missing, or malformed API key</TableCell>
      <TableCell>Check the `Authorization: Bearer <key>` header. No colon after Bearer. No whitespace in key value. Community Gateway does not require a key.</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**422**</TableCell>
      <TableCell>Invalid request body: malformed `model_id`, missing required field, or wrong content type</TableCell>
      <TableCell>Check the error body for the specific field. Ensure `model_id` uses a valid Hugging Face model ID string.</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**503**</TableCell>
      <TableCell>Model is cold: being loaded by an Orchestrator. Expected load time: 30 seconds to 5 minutes.</TableCell>
      <TableCell>Wait and retry with exponential backoff. This is expected behaviour, not a failure.</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**429**</TableCell>
      <TableCell>Rate limit exceeded on the Gateway</TableCell>
      <TableCell>Back off and retry after the rate limit window resets.</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**500**</TableCell>
      <TableCell>Inference error on the Orchestrator (model crash, OOM, or unexpected input)</TableCell>
      <TableCell>Check the error body for detail. Retry once. If persistent, check model\_id and input dimensions.</TableCell>
    </TableRow>
  </tbody>
</StyledTable>

<CustomDivider />

## Cold model timeouts

A model is "cold" when no Orchestrator on the network has it loaded in GPU memory. The first request triggers a model load, which takes 30 seconds to 5 minutes depending on model size and GPU.

A cold model returns a `503` or a long pending response. This is not an error in your code.

**Mitigation:** use warm models for latency-sensitive applications. The following models are kept warm across the network:

| Pipeline       | Warm model                               |
| -------------- | ---------------------------------------- |
| text-to-image  | `SG161222/RealVisXL_V4.0_Lightning`      |
| image-to-image | `timbrooks/instruct-pix2pix`             |
| audio-to-text  | `openai/whisper-large-v3`                |
| image-to-text  | `Salesforce/blip-image-captioning-large` |
| LLM            | `meta-llama/Meta-Llama-3.1-8B-Instruct`  |

Implement retry with exponential backoff for any request that may target a cold model:

```typescript icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
async function callWithRetry(fn: () => Promise<any>, maxRetries = 5): Promise<any> {
  let delay = 5000; // 5 seconds initial
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (err: any) {
      if (err.statusCode === 503 && attempt < maxRetries) {
        await new Promise(r => setTimeout(r, delay));
        delay = Math.min(delay * 1.5, 60000); // cap at 60 seconds
      } else {
        throw err;
      }
    }
  }
}
```

<CustomDivider />

## Diagnosing a non-responsive job

When a request hangs with no response, check in this order:

1. **Network connectivity** to the Gateway:
   ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
   curl -I https://dream-gateway.livepeer.cloud/text-to-image
   # Expect: HTTP 405 (method not allowed on GET is correct)
   ```

2. **Request construction** using curl to isolate from SDK behaviour:
   ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
   curl -v -X POST https://dream-gateway.livepeer.cloud/text-to-image \
     -H "Content-Type: application/json" \
     -d '{"prompt": "test", "model_id": "SG161222/RealVisXL_V4.0_Lightning"}'
   ```

3. **Model availability**: use a known warm model to confirm the integration works, then switch to your target model.

4. **Gateway availability**: if using a self-hosted or third-party Gateway, confirm the Gateway process is running and the HTTP port is reachable. For self-hosted Gateways, check `livepeer_cli -status` and the TicketBroker deposit balance.

5. **Orchestrator availability**: check `tools.livepeer.cloud/ai/network-capabilities` to confirm Orchestrators are advertising the pipeline and model you need.

<CustomDivider />

## 422 validation errors

A `422` response includes a body that identifies the failing field:

```json icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
{
  "detail": [
    {
      "loc": ["body", "model_id"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}
```

Common causes:

* `model_id` is missing (required on all pipelines)
* `model_id` format is wrong: must be a Hugging Face model ID string, e.g. `SG161222/RealVisXL_V4.0_Lightning`
* Image input sent as JSON instead of `multipart/form-data` (image-to-image, upscale, segment-anything-2)
* Dimension values are not integers (use `1024`, not `"1024"`)

<CustomDivider />

## Video transcoding and streaming failures

Video jobs fail for different reasons than AI jobs:

| Symptom                 | Likely cause                                  | Fix                                                                                   |
| ----------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------- |
| RTMP push rejected      | Stream key wrong or stream deleted            | Verify stream key matches the stream object                                           |
| HLS manifest empty      | Transcoding has not completed first segment   | Wait 5-10 seconds after RTMP connection                                               |
| Playback fails with 403 | Access control policy blocking playback       | Check JWT or webhook playback policy configuration                                    |
| Recording not available | Stream did not go idle cleanly                | Check `stream.idle` webhook; recording generates on idle                              |
| Webhook not firing      | Webhook URL unreachable or signature mismatch | Verify webhook URL is publicly reachable and `Livepeer-Signature` verification passes |

<CustomDivider />

## Getting help

If the above steps do not resolve the issue:

* **Discord:** `#lounge` and `#ai-research` channels in the [Livepeer Discord](https://discord.gg/livepeer). Include your request body (redact API keys), the response status, and the response body.
* **Forum:** [forum.livepeer.org](https://forum.livepeer.org) for in-depth debugging questions.
* **GitHub:** File an issue against [Livepeer/ai-runner](https://github.com/livepeer/ai-runner/issues) for AI failures or [livepeer/go-livepeer](https://github.com/livepeer/go-livepeer/issues) for video and node issues.

See [help](/v2/developers/guides/help) for the full channel reference.
