Errors & Diagnostics
Every error shape the harness returns, and how to tell a failed request from a failed run.
API errors
| Status | Shape | When |
|---|---|---|
401 | { "message": … } | Missing, invalid, or expired token. |
403 | { "message": … } | The token lacks the route's ability, or the team role doesn't permit the write. |
404 | { "message": … } | Unknown ID — or an ID outside your workspace, which is deliberately indistinguishable. |
409 | { "message": …, "id": "<ulid>" } | Saving a target whose domain already exists in the workspace. The existing target's ID is returned so you can adopt it instead of retrying. |
422 | { "message": …, "errors": { field: [msgs] } } | Validation — errors maps each field to its messages. |
429 | { "message": … } | Rate limited — see limits. |
A failed run is not an HTTP error
A session that can't complete — the target unreachable, a transport failure mid-funnel, a model error — still returns 200. The failure is carried in the result: error (the message) and error_type (a stable classifier), alongside whatever the run did complete. This is deliberate: the run happened, and its partial record is the diagnostic.
Agent page messages
Some runs are refused before they start. The Agent page shows the message as written here:
| Status | Message | What to do |
|---|---|---|
429 | Daily session limit reached (used/limit). Sign in for a higher limit. Resets … | Signed out, sessions are capped per day. Sign in, or wait for the reset. |
429 | Monthly session limit reached (used/limit). Resets … | Your plan's monthly cap — see Usage Dashboard. |
401 | Sign in to run the store-page door. | Store-page (WebMCP) runs need an account. Sign in and run again. |
422 | A store-page run is one task on our browser. Start a new session to run another. | A store-page run takes no follow-ups. Click New run. |
429 | You have used today's 10 store-page runs. They reset at midnight UTC. | Use a UCP connection, or wait for the reset. |
429 | All store-page browsers are still busy. Try again in a minute. | The run waited for a free browser and none came. Try again shortly. |
A store-page run can also fail at the start because of the page itself: "The page has no WebMCP (document.modelContext).", "The page registered no WebMCP tools.", or "The browser could not open the page: …". See Transport Failures.
Transport diagnostics
Each tool call in a session's record carries the full exchange — method, URL, request body, response status and body. When the call failed before any response (connection refused, timeout), the same record appears with a null status and an error field instead — so the debug view always shows what was attempted, not just what answered. Bodies are truncated at 4,000 characters, marked with a … (truncated) suffix.
For diagnosing the failures themselves — MCP handshake errors, REST fallback, OAuth — see Transport Failures and Common Errors.
Reference-store rejections
The reference store speaks a different dialect at its enforcement edge — an error code plus a stable reason:
{ "error": "tap_verification_failed", "reason": "signature expired" }The full reason table lives in Signature Verification.
Webhook verification failures
If your endpoint rejects a delivery, check the signature over the raw body: X-Playground-Signature is sha256= + HMAC-SHA256(raw bytes, webhook secret). The most common mismatch is verifying over re-serialized JSON — key order and escaping change the bytes. Compare digests constant-time, and remember deliveries never follow redirects.
Error messages may be reworded; treat shapes, status codes, error_type, and the reference store's reason strings as the stable contract.