- API-level errors — returned as non-2xx HTTP responses (auth, validation, rate limits, server errors).
- Run-response error codes — returned with HTTP 200 inside the
errorobject of a run response (agent failures, infrastructure issues that map to a finished run, cancellations).
Error Response Format
API-level errors contain anerror object with a code, a message, and optional details. The shape of details depends on the error code:
details is optional. For INVALID_INPUT (400), it can be an array of Zod validation issues containing code, path, message, and issue-specific fields. For VAULT_RECONNECT_REQUIRED (401), it can be an object containing providers, an array of provider ID strings such as 1password and bitwarden./v1/automation/run-batch can return a per-run validation envelope; see Batch Errors. Vault reconnect failures before enqueueing use the top-level error shape shown above.
API-level Error Codes
MISSING_API_KEY
HTTP Status: 401 TheX-API-Key header was not included in the request.
X-API-Key header to your request:
INVALID_API_KEY
HTTP Status: 401 The provided API key does not exist or has been revoked.- Verify your API key is correct (no extra whitespace)
- Check if the key was deleted in the API Keys dashboard
- Generate a new key if needed
UNAUTHORIZED
HTTP Status: 401 Authentication failed for a reason other than missing/invalid key. For example, required user context may be missing. Expired vault credentials useVAULT_RECONNECT_REQUIRED.
- Check your account status at agent.tinyfish.ai/api-keys
- For Vault-related calls, reconnect your vault under Settings → Vault
- Try generating a new API key
VAULT_RECONNECT_REQUIRED
HTTP Status: 401 A vault connection needs replacement credentials. Reconnect the affected provider from the Vault page, then retry the request. Vault-backed runs reject credentials already marked expired before enqueueing; other provider-scoped runs can remain usable. The TypeScript and Python SDKs preservecode = "VAULT_RECONNECT_REQUIRED" on the authentication exception. Check this code to distinguish vault recovery from an invalid TinyFish API key. Responses may identify affected provider IDs in error.details.providers.
CLI users can reconnect with tinyfish vault connection add --provider 1password or tinyfish vault connection add --provider bitwarden --client-id <client-id>. Supply the replacement 1Password token through TINYFISH_VAULT_TOKEN, or Bitwarden secrets through TINYFISH_VAULT_CLIENT_SECRET and TINYFISH_VAULT_MASTER_PASSWORD, then retry. CLI guidance requires an updated CLI version.
INVALID_INPUT
HTTP Status: 400 The request body failed validation.urlis missing or not a valid URL (must includehttps://)goalis empty or missingbrowser_profileis not"lite"or"stealth"proxy_config.country_codeis not a supported 2-letter code (US, GB, CA, DE, FR, JP, AU)output_schemais invalid JSON Schema- Missing required query parameter (e.g.
queryon/v1/search)
details field for specific validation errors. Each entry includes the failing field path and a human-readable message.
FORBIDDEN
HTTP Status: 403 Authentication succeeded, but the request was rejected — usually because the account lacks an entitlement, capability, or remaining credits. The credit case applies to legacy credit/subscription accounts only; wallet accounts getINSUFFICIENT_CREDITS at 402 instead.
- No remaining credits or expired subscription on a legacy credit/subscription account
proxy_config.type: "custom"requested without the custom-proxy entitlementoutput_schemaprovided without the output-schema entitlementcapture_configrequests a capability the account isn’t enabled for- Attempting to access a resource you don’t own
message field always specifies which entitlement or condition failed.
INSUFFICIENT_CREDITS (wallet accounts)
HTTP Status: 402 The account’s TinyFish wallet balance is too low to start this run. This is a pre-flight check — the run is never created, and it is not retryable until money is added. Runs are never cut off mid-flight: a run already in progress finishes even if it takes the balance negative, and it’s the next one that gets denied.- Wallet balance is zero or negative
- Auto-reload is paused because the payment method on file was declined
details carries machine-readable fields (balance, currency, wallet_url, minimum_top_up, auto_reload_needs_payment_fix) so REST callers can act on the denial without parsing message. /v1/automation/run-batch includes the same details object on its wallet-denial error slot.
Solution: Add money at agent.tinyfish.ai/wallet (minimum top-up $10), or update the payment method if auto-reload is paused, then retry.
FEATURE_NOT_AVAILABLE
HTTP Status: 404 The account is not enabled for the requested feature. Currently emitted only byGET /v1/wallet, when the account is on legacy credit/subscription billing rather than a wallet — this is the discriminator for telling the two billing modes apart at request time.
NOT_FOUND
HTTP Status: 404 The requested resource does not exist.- Invalid
run_idinGET /v1/runs/:id - Vault connection not found
- Browser context profile not found
- Step HTML/screenshot not found (
GET /v1/runs/:id/steps/:stepId/...) - Run was deleted or never existed
- Run ID belongs to a different token scope — CLI/REST run IDs and MCP run IDs live in separate scopes, so a CLI lookup for an MCP-created run returns 404 by design
/v1/automation/run-async or can be listed via GET /v1/runs.
RETRY_REQUIRED
HTTP Status: 409 A transient conflict prevented the request from completing. Currently emitted by Browser Context Profile setup endpoints (/v1/profiles/:id/save, /v1/profiles/:id/setup-session, /v1/profiles/:id/setup-session/cancel) when the setup session is in an intermediate state.
RATE_LIMIT_EXCEEDED
HTTP Status: 429 Too many requests in a short period.message wording varies by endpoint. Read details instead of parsing it:
details is present when your account’s per-minute limit rejected the call, which is the case this section describes. Two other conditions also return RATE_LIMIT_EXCEEDED and deliberately omit details, because no change to your plan would clear them:
- The upstream search or fetch provider throttled the request. Retry with backoff.
- Our rate-limit store was unavailable and the request failed closed. Retry with backoff.
- The automation pending-run cap was hit. Wait for existing runs to finish.
details as “retry, do not upsell”.
Rate limits depend on your account’s limits and which API you’re calling:
/v1/searchand/v1/fetchenforce per-minute request limits, applied per API key./v1/automation/run,/run-async, and/run-batchenforce a pending-run cap tied to your account’s concurrency limit.
details.upgrade_url from the error body.
Response headers:
The automation pending-run cap (429 from
/v1/automation/run, /run-async, /run-batch) does not set Retry-After or X-RateLimit-Limit — wait for existing runs to finish and retry. The body message includes your current count and the maximum.- Respect
Retry-Afterwhen present, otherwise implement exponential backoff - Space out requests (recommended: 1-2 seconds between calls)
- Use batch endpoints for high-volume workloads
- Request a higher limit by following
details.upgrade_urlfrom the error body
DAILY_LIMIT_EXCEEDED
HTTP Status: 429 The account reached its daily allowance for a capability. Research (POST /v1/automation/run-research) counts runs
started per Pacific calendar day, including runs still in progress. Runs that fail, time out, or are cancelled do not
count.
Response headers:
Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds).
Solution: Wait for resets_at, or contact support to raise the allowance. Unlike RATE_LIMIT_EXCEEDED, backoff
within the same day will not clear this error.
INTERNAL_ERROR
HTTP Status: 500 An unexpected error occurred on the server.- Retry the request after a brief delay
- If the error persists, check agent.tinyfish.ai/status for outages
- Contact support with your request details and timestamp (include
X-Request-IDif you have it)
Run-response Error Codes
Once a run is accepted, completion-time failures are reported inside the run response body — not as HTTP error codes. The HTTP response is 200, and you inspectstatus + error:
category field gives you a quick branching key:
Optional fields:
retry_after— suggested delay in seconds (nullif not retryable)help_url— link to troubleshooting docshelp_message— short human-readable guidance
SERVICE_BUSY
Category:SYSTEM_FAILURE · In-body HTTP: 200
The platform is temporarily out of capacity (browser pool exhausted, dependent service unavailable). Equivalent to a 503 if returned at the HTTP layer.
Solution: Retry with exponential backoff.
TIMEOUT
Category:SYSTEM_FAILURE · In-body HTTP: 200
An infrastructure or request timeout terminated the run. Equivalent to a 504.
Solution: Retry. If the goal is large/multi-step, consider splitting it or simplifying.
BILLING_REJECTED
Category:BILLING_FAILURE · In-body HTTP: 200
The run was rejected at the billing check before execution — the wallet balance was too low, or a legacy account was out of credits. The agent never started, so the run lands in a terminal CANCELLED status with no steps recorded. Runs are never cut off mid-flight: one already in progress finishes even if it takes the balance negative, and it’s the next one that gets denied.
The same condition can also be caught earlier and reported at the HTTP layer, before the run record is created — INSUFFICIENT_CREDITS at 402 for wallet accounts, FORBIDDEN at 403 for legacy credit/subscription accounts. Handle both.
Solution: Add money at agent.tinyfish.ai/wallet — minimum top-up $10. Legacy accounts add credits at agent.tinyfish.ai/api-keys. Then retry.
CONTENT_POLICY_VIOLATION
Category:AGENT_FAILURE · In-body HTTP: 200
The request — typically the goal text or a target URL — was blocked by content policy.
Solution: Adjust the goal or target. Contact support if you believe the block was a false positive.
MAX_STEPS_EXCEEDED
Category:AGENT_FAILURE · In-body HTTP: 200
The automation hit the configured maximum step count without producing a result.
Solution: Simplify the goal, split it into multiple runs, or raise the step limit if your account’s limits allow it.
SITE_BLOCKED
Category:AGENT_FAILURE · In-body HTTP: 200
The target site blocked the automation (anti-bot, CAPTCHA, IP block). The status field is still FAILED.
Solution: Switch browser_profile to "stealth", attach a proxy via proxy_config, or use a Browser Context Profile with a warmed session. See the anti-bot guide.
TASK_FAILED
Category:AGENT_FAILURE · In-body HTTP: 200
The agent ran but couldn’t achieve the goal — navigation failed, content not found, authentication required, the result was incorrect, or the task wasn’t achievable as described.
Solution: Make the goal more concrete (which page, which selector-equivalent description, which field). See the prompting guide. For auth flows, use a vault credential or a saved profile.
CANCELLED
Category: N/A · Status:CANCELLED · In-body HTTP: 200
The run was cancelled — either by you (POST /v1/runs/:id/cancel), by SDK cancellation, or because the async task lifecycle was terminated. Not an error in the usual sense.
Solution: No action needed unless the cancellation was unintended.
Batch Errors
/v1/automation/run-batch validates the whole request first, then dispatches each child run. Batch-level failures (auth, missing capability, validation) follow the standard { "error": { "code", "message" } } shape, with an optional details object on wallet-denial (INSUFFICIENT_CREDITS, 402) errors — see the example above. Per-run dispatch errors are returned inside the batch response under each run’s slot. Treat the batch envelope as “did the batch get accepted?” and inspect each child for “did the individual run get scheduled?”
Run Status vs Error Codes
HTTP error codes (the table below) indicate request-level failures — your request didn’t make it to the agent. Run-response error codes indicate completion-level outcomes — the run reached the worker and reported back.For more on COMPLETED-but-failed runs, see Understanding Run Status.
HTTP Status Code Summary
Related
Authentication
API key setup and troubleshooting
FAQ
Common questions and issues