# Errors Every error has this shape. Branch on `code`, not on `message`. ```json { "code": "start_rate_limited", "message": "This project has used its 60 starts for this minute.", "fix": "Retry after 14 seconds, or send placement: \"queue\" to wait in line.", "status": 429, "request_id": "req_01J9ZK", "retry_after_seconds": 14, "docs_url": "https://harebox.com/docs/reference/errors.html#start_rate_limited" } ``` ## Safe retry rules | Situation | Retry? | |---|---| | `retry_after_seconds` present | Yes, after that time | | Any 5xx on a request with `Idempotency-Key` | Yes, with the same key | | Network error on a request with `Idempotency-Key` | Yes, with the same key | | 4xx without `retry_after_seconds` | No. Change the request. | | `idempotency_outcome_unknown` | Not with the same key. Check whether it worked, then use a new key if it didn't. | | `POST` with no idempotency key after a timeout | Check state first. It may have worked. | ## Codes | Status | Code | Meaning | What to do | |---|---|---|---| | 400 | `invalid_request` | A field is wrong; `details` names it | Fix the field | | 401 | `invalid_credential` | Key missing, expired or revoked | Sign in or rotate | | 400 | `trial_auto_stop_required` | The trial needs an auto-stop of 2 hours or less | Send `ttl_seconds` of 7200 or less, or end the trial | | 402 | `payment_required` | No credit and grace has ended | A human adds funds | | 402 | `billing_required` | No plan, or an extra start the wallet can't pay | Start a plan, or add to the wallet | | 402 | `card_required` | The trial or a plan needs a card on file | A person runs `harebox billing card` | | 402 | `subscription_required` | The wallet needs a plan first | Start a plan | | 402 | `budget_exceeded` | A hard budget blocked this | The owner raises the budget | | 403 | `scope_missing` | Key lacks a scope; `details` names it | Use another key | | 403 | `target_forbidden` | Key cannot reach this sandbox | Check selectors | | 403 | `size_not_allowed` | The plan doesn't offer this size; `details.allowed` lists what it does | Pick an allowed size, or move up a plan | | 403 | `templates_not_allowed` | Saving templates needs a paid plan | End the trial | | 403 | `claim_required` | Only a claimed account can add a card | A person opens the `claim_url` | | 404 | `not_found` | No such resource, or no access | Check the ID | | 409 | `idempotency_outcome_unknown` | An earlier attempt with this key was interrupted by a server failure, so it may or may not have taken effect | List the resources, then use a new key if it didn't work | | 422 | `idempotency_key_reused` | This key was already used with a different request body | Use a new key | | 409 | `invalid_state` | Wrong state; `details.state` gives it | Wake or resume first | | 409 | `sandbox_starting` | Still starting after a 60 s wait | Retry | | 409 | `capability_unavailable` | Not possible right now | Read `capabilities` | | 409 | `data_expired` | Past retention, with no archive | Cannot be recovered | | 409 | `requires_active_plan` | Auto top-up needs a paid plan | End the trial first | | 429 | `start_rate_limited` | Past the ceiling of extra starts, or the trial's starts; `details.cause` says which | Wait, `placement: queue`, or a larger plan | | 429 | `trial_compute_limit_reached` | The trial used its 25 hours | End the trial | | 429 | `concurrency_limited` | Too many running | Stop one, or upgrade | | 429 | `member_cap_reached` | An owner capped this member | Ask the owner | | 429 | `api_rate_limited` | Too many API calls | Follow `retry_after_seconds` | | 503 | `no_capacity` | No machine now; running VMs unaffected | Retry, or queue with `placement: "queue"` | ## CLI exit codes | Code | Meaning | |---|---| | 0 | Success | | 1 | General failure | | 2 | Usage | | 3 | Auth | | 4 | Not found | | 5 | Wrong state | | 6 | Limit or budget | | 7 | Capacity | | 8 | Network | `harebox exec` returns the remote command's own exit code.