# Error Handling

Handle common Mighty errors, billing states, limits, rate limits, and async states.

Source URL: https://trymighty.ai/docs/integrate/errors

## Goal

Build safe fallback behavior for scan errors.

High-risk workflows should fail to review. Low-risk workflows can retry or degrade with clear limits.

## Error Shape

Errors may include an error message, code, request ID, and scan group ID.

```json
{
  "error": "scan_phase must be 'input' or 'output'",
  "code": "invalid_scan_phase",
  "request_id": "ab82f4ad-8d64-4bb4-b4ed-77df63291198",
  "scan_group_id": "9b3e4f8d-96c9-4f42-8338-8cf9571c1c70"
}
```

## Status Codes

| Status | Meaning | Fix |
| --- | --- | --- |
| `400` | Bad request. | Check `scan_phase`, `content_type`, UUID fields, and payload shape. |
| `402` | Billing, quota, spending limit, or tier cap. | Show upgrade, route to admin, or route to review. |
| `409` | Idempotency or duplicate request conflict. | Fetch existing result or retry with a new `request_id`. |
| `413` | Payload too large, PDF page cap, embedded image cap, or payload complexity. | Reduce size, split the file, remove excess embedded images, or review manually. |
| `429` | Rate limited. | Retry with backoff and queue the workflow. |
| `500` | Server error. | Retry safely, then route to review. |

## Safe Fallback Policy

```ts
export function fallbackForScanError(status: number, workflowRisk: "low" | "high") {
  if (status === 400) return "fix_request";
  if (status === 402) return "billing_or_tier_action";
  if (status === 413) return "reduce_or_review";
  if (status === 429) return "retry_with_backoff";

  return workflowRisk === "high" ? "manual_review" : "retry_then_degrade";
}
```

## Common 400 Causes

- Missing `scan_phase`.
- `scan_phase=output` without `scan_group_id`.
- Invalid UUID in `request_id` or `scan_group_id`.
- `content_type` outside `auto`, `text`, `image`, `pdf`, or `document`.
- Unsupported `focus` for the resolved content type. For example, `content_type=document` supports `focus=steg`; `focus=ai`, `focus=edits`, `focus=all`, and deprecated `focus=both` return `code=unsupported_focus_for_content_type`.
- Base64 missing when JSON contains non-text content.
- Multipart request without `file` or `content`.

## Billing And PDF Limit Errors

PDFs have two separate dimensions:

- Page count.
- Unique embedded image count.

Billing is additive. Pages stay 2 SCU each. Unique embedded images use the active focus image-unit price:

```text
Focused PDF SCU = pages * 2 + unique embedded images * 4
All-evidence PDF SCU = pages * 2 + unique embedded images * 10
```

Tier caps are separate from SCU. A scan can be blocked before billing if the PDF exceeds the tier's page or embedded image limit.

| Condition | Typical status | Route |
| --- | --- | --- |
| Missing payment method, quota, spending limit, or tier upgrade required | `402` | Show billing or admin action. |
| PDF exceeds allowed page count | `402` or `413` depending on entry point | Ask user to split the PDF or upgrade. |
| PDF exceeds allowed unique embedded image count | `402` or `413` depending on entry point | Ask user to reduce images, split the PDF, or upgrade. |
| Raw upload is too large | `413` | Reduce file size or route to manual review. |

## Async States

| State | Meaning | Route |
| --- | --- | --- |
| `pending` | Deep scan is still running. | Keep pending or poll again. |
| `complete` | Final result is ready. | Route by `action`. |
| `failed` | Deep scan failed. | Manual review or safe stop. |

## Retry Rules

- Retry `429` with exponential backoff.
- Retry network errors with a unique `request_id` unless your app already committed the prior request.
- Do not retry `400` until the request is fixed.
- Do not hide `402` or `413`. Those need product routing.
- Keep webhook processing idempotent.

## AI-Agent Prompt

### Add Mighty error handling

```text
Add robust Mighty error handling.

Requirements:
- Parse non-2xx responses.
- Handle 400 as a developer or request shape error.
- Handle 402 as billing, quota, or tier cap.
- Handle 409 as idempotency conflict.
- Handle 413 as file size, PDF page cap, embedded image cap, or payload complexity.
- Handle 429 with backoff.
- Treat async pending as pending, not as final.
- Treat async failed as manual review for high-risk workflows.
- Include request_id and scan_id in logs when available.

Acceptance criteria:
- Tests cover 400, 402, 409, 413, 429, network error, pending, complete, and failed.
- High-risk workflows never continue silently after a scan failure.
```
