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

# Errors

> The closed 31-code error union.

export const OutcrawlStyles = () => {
  if (typeof document !== 'undefined' && !document.getElementById('outcrawl-overrides')) {
    const s = document.createElement('style');
    s.id = 'outcrawl-overrides';
    s.textContent = `
      /* Match the product's radius grid (4 / 6 / 8 / 9999), not Mintlify's default. */
      .rounded-sm { border-radius: 0.375rem !important; } /* 6px, --r-ctl */
      .rounded-md { border-radius: 0.375rem !important; } /* 6px, --r-ctl */
      .rounded-lg { border-radius: 0.5rem !important; }   /* 8px, --r-panel */
      .rounded-l-sm { border-top-left-radius: 0.375rem !important; border-bottom-left-radius: 0.375rem !important; }
      .rounded-r-sm { border-top-right-radius: 0.375rem !important; border-bottom-right-radius: 0.375rem !important; }
      .rounded-l-md { border-top-left-radius: 0.375rem !important; border-bottom-left-radius: 0.375rem !important; }
      .rounded-r-md { border-top-right-radius: 0.375rem !important; border-bottom-right-radius: 0.375rem !important; }
      .rounded-l-lg { border-top-left-radius: 0.5rem !important; border-bottom-left-radius: 0.5rem !important; }
      .rounded-r-lg { border-top-right-radius: 0.5rem !important; border-bottom-right-radius: 0.5rem !important; }

      /* Cards: never pure white in light mode, matching the one-big-card surface tone. */
      .card { background-color: #fcfcfc !important; border-radius: 0.5rem !important; }
      html.dark .card { background-color: #141311 !important; }

      /* Docs hero box */
      .oc-hero { background-color: #fcfcfc; border: 1px solid #e5e2dc; }
      html.dark .oc-hero { background-color: #141311; border-color: #26241f; }
      html.dark .oc-hero h1 { color: #edeae4; }

      /* Thin, transparent-track, hide-until-hover scrollbar. */
      ::-webkit-scrollbar { width: 6px; height: 6px; background-color: transparent; }
      ::-webkit-scrollbar-track { background-color: transparent; }
      ::-webkit-scrollbar-thumb { background-color: rgba(155, 155, 155, 0.5); border-radius: 10px; transition: opacity 0.3s ease; opacity: 0; }
      ::-webkit-scrollbar-thumb:hover { background-color: rgba(155, 155, 155, 0.7); }
      *:hover::-webkit-scrollbar-thumb,
      *:focus::-webkit-scrollbar-thumb,
      *:active::-webkit-scrollbar-thumb { opacity: 1; }
      * { scrollbar-width: thin; scrollbar-color: rgba(155, 155, 155, 0.5) transparent; }
    `;
    document.head.appendChild(s);
  }
  return null;
};

<OutcrawlStyles />

Every failed request answers the same envelope:

```json theme={"theme":{"light":"github-light","dark":"catppuccin-mocha"}}
{
  "code": "quota_exceeded",
  "message": "...",
  "details": {}
}
```

Branch on `code`. It is a closed set of 31 values; `message` is fixed per code and is never meant to be parsed.

| Code | Meaning |
| - | - |
| `unauthorized` | The key was missing, invalid, or not on the allowlist |
| `bad_request` | Malformed or missing input, fixable and retryable after a fix |
| `not_found` | No such resource, or none this key can see |
| `method_not_allowed` | Wrong HTTP method for the route |
| `plan_required` | The key is valid but names no plan this deployment can serve |
| `quota_exceeded` | The account is over a ceiling its plan sets (requests per minute, or monthly credits) |
| `concurrency_limit` | The account is holding every browser its plan allows at once |
| `cap_exceeded` | The request itself is over a ceiling the caller set on that one call |
| `capability_unavailable` | This deployment has nothing configured to serve the capability |
| `no_capacity` | No worker is free right now |
| `exit_unavailable` | No exit could be resolved for the requested geography |
| `tenant_scope` | A connection touched a target outside its own tenant |
| `profile_in_use` | The named profile is leased by another open session |
| `profile_not_found` | No such profile, or it belongs to another account |
| `page_unreachable` | No response arrived at all, resolution or connection failed |
| `page_lost` | The tab stopped existing before the page could be delivered |
| `document_unrepresentable` | The bytes arrived and cannot be turned into text |
| `decode_unavailable` | A stored recording cannot be decoded right now |
| `extraction_failed` | A schema'd extraction did not produce a matching document |
| `answer_lost` | The work finished but the answer never reached the edge |
| `deadline_exceeded` | The caller's own timeout was exceeded by work already done |
| `lab_arm_forbidden` | An agent run asked for an internal experiment this account is not enrolled in; only Outcrawl's own test runs send that, so drop the header |
| `search_refused` | Every search engine tried declined the search; nothing was charged, and a retry goes out from another exit |
| `integration_check_failed` | Connecting or updating an integration ran its check against the MCP server and it failed (422); `details.reason` is `not_mcp`, `unauthorized`, `unreachable` or `missing_secret`, and nothing was stored |
| `integration_changed` | The integration was replaced under the same name between your read and your update (409); nothing was stored, read it again |
| `secret_intent_invalid` | A `PUT` to a secret intent's URL carried a token that does not open it (401); nothing was stored |
| `secret_intent_spent` | The secret intent was already used, expired after five minutes, or its key was revoked (410); mint a new intent |
| `replay_access_denied` | This credential may not read this recording (403); `details.reason` says why, and `operator_key` means a key issued by Outcrawl staff, which never opens a customer's recordings |
| `replay_control_denied` | Someone watching a shared recording asked to drive it (403); only the owning account's key or team can take control |
| `replay_control_cross_site` | A request to drive a live session came from another site with only the player's cookie (403); use the player's own controls or send a key in a header |
| `internal` | Something broke on our side |

## What is retryable

Some of the above resolve on their own and are safe to retry unchanged: `no_capacity`, `decode_unavailable`, `extraction_failed` and `answer_lost` are all cases where the identical call commonly succeeds moments later. The rest are not: retrying a `bad_request` or a `quota_exceeded` without changing anything spends money to fail the same way again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.