# Errors and retry rules

## Notebook errors

HTTP notebook failures use `{"error":{"code":"...","message":"..."}}`. MCP notebook failures use `isError: true` and that JSON in text content. Protocol-level MCP argument failures may use the SDK's validation error format instead. The MCP SDK rejects inputs exceeding 2,000 cumulative array elements/object members as an invalid-arguments protocol error before notebook execution. Reduce the argument structure rather than retrying it unchanged.

Messages are for people; branch on known codes, status and operation context rather than exact message text.

- `invalid_input` / HTTP 400: malformed or unknown fields, bad IDs, invalid cursor or limits. Correct the request. Do not retry unchanged.
- `forbidden` / HTTP 403: access or scope is insufficient, or the browser Origin/CSRF binding is wrong. Stop and resolve the actual authorization/session issue. Do not switch owners or keep retrying.
- `not_found` / HTTP 404: missing entry or entry in another codex. Do not infer whether another owner has that ID.
- `conflict` / HTTP 409: reused save key with different input, or a stale update revision. Reconcile the original save input or retrieve the latest entry before any change.
- `unavailable` / HTTP 503: backend, verification or storage is unavailable. A bounded retry may be appropriate. Treat a lost mutation response as uncertain, not as failure to execute.

The browser auth layer returns `invalid_sign_in` or `invalid_assertion` with HTTP 401 for invalid, expired or replayed sign-in material. The router uses sanitized codes rather than exposing each verification failure. Do not fabricate consent or confuse upstream Passport app-consent errors with this application's error codes. A verifier/storage outage is 503. [The HTTP reference](/docs/http.md) defines additional transport limits and routes.

Approval and callback delivery alone do not create a browser session. The original dashboard's challenge deadline is not extended by approval. If it expires before confirmation, start a fresh dashboard sign-in once and obtain a new approval; never reuse the old code or assertion. If confirmation was submitted but its response was lost or arrived too late to verify, use Check session before starting again. The server may already have completed that confirmation.

## Save retry

Preserve the same `requestId` and the same entry input after a timeout or lost response. A different key can create a duplicate. A different entry under the same key conflicts. A successful replay returns the current revision; it is not a snapshot of the initial save response.

## Update retry

Updates are not idempotent. After any uncertain result, retrieve the entry. Compare content and revision to determine whether the intended replacement was already applied. Never increment `expectedRevision` blindly. On a real conflict, reconcile rather than overwriting another client's edits.

## Search and get retry

Reads may be repeated with a bounded retry policy for transient unavailability. Keep the same identity and search filters. Concurrent writes can change results, so a repeated page is not a snapshot guarantee. Follow returned cursors, including after empty pages, within the task's time and cost budget.

## Browser and transport failures

- HTTP 413: JSON exceeds the route's body cap. Reduce the payload; do not loop.
- HTTP 429 `rate_limited`: sign-in begin/callback quota was reached. Wait rather than repeatedly minting assertions. No `Retry-After` guarantee is defined by the current router.
- HTTP 405: unsupported method on a route with an explicit method guard, such as `/health` or the closed MCP candidate. Not every unknown method is guaranteed to return 405; unmatched application routes return 404.
- HTTP 501 `not_implemented` at the default function's `/mcp` boundary: remote OAuth is not configured. Public Hosting does not currently rewrite `/mcp`, so its public result may be a Hosting 404 instead. Neither response is a login instruction.

A future closed MCP resource candidate distinguishes invalid access (401), inadequate scopes (403) and verifier/storage outages (503). Do not treat every 503 as expired credentials. Production remote-client behavior remains unverified.

## Approval and code-exchange uncertainty

Do not repeat an owner approval or OAuth code exchange blindly after losing its response. The closed OAuth experiment has single-use decisions/codes, and correctly bound code replay revokes the original grant. It has no refresh or outcome-recovery endpoint. This is candidate behavior, not an instruction to use it live.
