Mobilebox
Menu
Errors and recoveryDocs pages and contents

On this page

Errors and recovery

A request error has an error object with code, message, next, retryable, and sometimes retry_after. Read next first. A retryable error can succeed later; it does not guarantee that replaying a state-changing request is safe.

json
{
  "error": {
    "code": "box_full",
    "message": "Illustrative capacity error",
    "next": "Wait before retrying.",
    "retryable": true,
    "retry_after": 15
  }
}

This illustrates the shape; use the actual response’s guidance and delay. HTTP errors are separate from per-action errors: POST actions can return HTTP 200 with results[i].ok=false. The batch stops at the first failure and returns the current screen.

Decide what failed

SignalMeaningNext step
401 unauthorizedMissing, wrong or revoked bearer keyCorrect the API key; a browser cookie is not an API key
400 invalid_requestInvalid query/body, unknown field or typeCorrect the shape; include Content-Type for JSON
409 idempotency_conflictThis create key already made a phone with other optionsResend the original options, or use a new key
410 phone_deletedThe phone this create key made was deletedUse a new key for a new phone
413 body_too_largeJSON exceeds 256 KBReduce the payload
413 apk_too_largeInstall upload exceeds 300 MiBSupply a smaller compatible build
429 phone_limitProject running/total phone capInspect phones; park or intentionally delete one
503 box_fullShared host cannot accept another phoneRespect Retry-After / retry_after
stale_refTarget belongs to an old screenObserve again and select a fresh target
type_not_appliedText did not arrive in a focused fieldObserve, focus or target the field, then type
signature_mismatchInstalled app and update have different signaturesObtain the matching build or intentionally uninstall with data loss
batch_timeoutBatch stopped starting actions at its time budgetInspect completed results and current screen

The table is a recovery guide, not an exhaustive error-code registry. Backend device/app failures carry more specific next guidance. Do not interpret every non-200 response as a transient host failure.

A create response still says creating

wait=ready waits within a bounded request, not indefinitely. Save the returned id and poll GET /v1/phones/{id}?wait=ready&timeout=50. Continue while creating/starting, stop on ready or failed, and enforce your own overall deadline. Creating a second phone does not accelerate the first one.

If a create request fails at the network boundary before you receive a response, repeat it with the same Idempotency-Key header and options (MCP: idempotency_key): within 24 hours you get the phone the first request made, with no second charge. Without a key, list phones before repeating it; a second POST can create a second billable phone. See retry a create safely.

An action failed after earlier actions succeeded

Earlier actions remain applied. Do not replay a full batch containing a submit, message send, delete, or purchase. Inspect results and the returned screen; continue from the last confirmed state. Verify the intended outcome before deciding to retry a side effect.

References are intentionally short-lived. Prefer current text, resource id, or content-description targets. Use screenshots for UI absent from the element tree. See targeting and recovery.

The MCP call did not throw

Protocol success does not prove application success. Tool errors use isError with recovery text. The act tool reports per-action results in text; a failed action can be part of a normal tool result. Read the entire result and new screen before planning the next call.

Cleanup after a failure

Park when app data should remain; delete when the sandbox is disposable. Do this even when the main task failed. Server idle/duration limits are a backstop, not a reason to skip cleanup. Keep the phone id somewhere the cleanup path can reach, and report a cleanup error separately from the original failure.

Source: docs/ERRORS.md in the repo, rendered at build time.