Errors
Every refusal is an RFC 9457 Problem, served as application/problem+json. Its code is stable: branch on that, not on the title or the detail.
The shape of a Problem
{
"type": "https://rent.dev/problems/unsupported_parameter",
"title": "Unsupported parameter",
"status": 400,
"code": "unsupported_parameter",
"docs_url": "https://rent.dev/docs/errors#unsupported_parameter",
"detail": "Unsupported parameter: region.",
"request_id": "req_01JCZ9Q4M8V7K2T3N5P6R8S0W1",
"errors": [
{
"path": "region",
"message": "Unsupported parameter."
}
]
}| Member | Type | Description |
|---|---|---|
type | string | Required. URI identifying the problem type. |
title | string | Required. |
status | integer, 100 to 599 | Required. |
code | insufficient_balance | account_frozen | key_limit_reached | payment_required | payment_failed | unsupported_parameter | invalid_request | unauthenticated | forbidden | not_found | method_not_allowed | conflict | idempotency_in_flight | gone | idempotency_key_reused | rate_limited | internal_error | not_implemented | vendor_error | no_capacity | vendor_timeout | claim_invalid | claim_proof_invalid | checks_failed | node_exists | supply_link_unavailable | node_revoked | node_suspended | node_replay | probe_in_progress | payout_proof_required | agent_upgrade_required | Required. Stable machine-readable error code. |
detail | string | |
instance | string | |
request_id | string | |
docs_url | string | |
balance_required_micros | integer | Additional balance, in micro-USD, that would let the request succeed. |
hold_id | string | hold_ followed by a 26-character ULID. |
retry_after | integer, at least 0 | Seconds to wait before retrying; mirrors the Retry-After header. |
topup | TopupLinks | |
errors | array of object | Per-field details. |
docs_url points at the code's entry on this page. request_id is also in the X-Request-Id response header of every call.
Codes
| Code | Status | Title |
|---|---|---|
| insufficient_balance | 402 | Insufficient balance |
| account_frozen | 402 | Account frozen |
| key_limit_reached | 402 | Key spend limit reached |
| payment_required | 402 | Payment required |
| payment_failed | 402 | Payment failed |
| unsupported_parameter | 400 | Unsupported parameter |
| invalid_request | 400 | Invalid request |
| unauthenticated | 401 | Authentication required |
| forbidden | 403 | Forbidden |
| not_found | 404 | Not found |
| method_not_allowed | 405 | Method not allowed |
| conflict | 409 | Conflict |
| idempotency_in_flight | 409 | Request with this Idempotency-Key in flight |
| gone | 410 | Gone |
| idempotency_key_reused | 422 | Idempotency-Key reused with a different payload |
| rate_limited | 429 | Rate limited by the vendor |
| internal_error | 500 | Internal error |
| not_implemented | 501 | Not implemented |
| vendor_error | 502 | Vendor error |
| no_capacity | 503 | No capacity |
| vendor_timeout | 504 | Vendor timeout |
| claim_invalid | 410 | Claim token used or expired |
| claim_proof_invalid | 401 | Claim proof does not verify |
| checks_failed | 422 | A blocking check failed |
| node_exists | 409 | Host already enrolled as a node |
| supply_link_unavailable | 503 | Node link unavailable |
| node_revoked | 410 | Node revoked |
| node_suspended | 403 | Node suspended |
| node_replay | 409 | Node request replayed |
| probe_in_progress | 409 | Probe in progress |
| payout_proof_required | 403 | Payout change needs a signed nonce |
| agent_upgrade_required | 400 | Node agent too old |
insufficient_balance
402. The balance cannot cover the hold this call needs. Add at least balance_required_micros through one of the topup links, then send the request again.
account_frozen
402. The balance is below zero, so no new hold is taken. Top up until it is positive.
key_limit_reached
402. This API key has reached its spend_limit_micros, counting what its running sandboxes hold. Raise the limit with PATCH /v1/keys/{id}, from a key without a limit, or use another key.
payment_required
402. The x402 route was called without a payment. Sign the requirement in the PAYMENT-REQUIRED header and send the request again with PAYMENT-SIGNATURE.
payment_failed
402. The x402 payment was refused; detail says why. Sign a new payment and send it again.
unsupported_parameter
400. The request names something this API, or the endpoint the sandbox runs on, cannot do. errors names the parameter. Remove it and retry.
invalid_request
400. The request is malformed. errors lists each field and what is wrong with it. An id in routing.allow that names no endpoint is one such field: detail lists the ids that exist.
unauthenticated
401. No credentials, or a key that is unknown or revoked. Send Authorization: Bearer rent_sk_…. POST /v1/accounts creates an account and a key.
forbidden
403. The access token lacks the scope this route needs; detail names it. Ask for a token with that scope. An API key with a spend limit gets this on a call that changes keys, agent keys, wallets or people, on one that changes how the account pays (setting auto-recharge or starting to save a payment method), on storing or deleting a vendor key, and on extending or resuming a sandbox another key started: use a key without a limit, or sign in. The agent quickstart lists what such a key can still do.
not_found
404. Nothing has this id on your account. A resource that belongs to another account answers the same.
method_not_allowed
405. The path exists but does not take this method.
conflict
409. The resource is not in the state this call needs, such as pausing a sandbox that is not running. Read it and decide again.
idempotency_in_flight
409. The first request with this Idempotency-Key is still running. Wait and send the same request again.
gone
410. The pay link has expired. Any new 402 carries a fresh one.
idempotency_key_reused
422. This Idempotency-Key was already used with a different request. Use a new key for a new request. On a signup it also means the account that key created has been used since, so no new API key is issued for it.
rate_limited
429. A vendor's rate limit, passed through. Wait retry_after seconds and send the request again.
internal_error
500. A fault on rent.dev's side. Retry, and quote request_id if it keeps happening.
not_implemented
501. The route is documented but not served in this environment. detail says which.
vendor_error
502. The vendor behind the endpoint failed. Send the request again.
no_capacity
503. No endpoint can take the request now. Retry after retry_after seconds, or allow another endpoint in routing.allow. On a GPU pod it means RunPod has none of that GPU left: retry later, or ask for another gpu_type or cloud_type.
vendor_timeout
504. The vendor did not answer in time. Read the resource before retrying, since the call may have gone through.
claim_invalid
410. A claim token works once, before it expires. When up made the enrolment, run rentdev-node up --re-enroll. When the token was made elsewhere, make a new one there and run the same line again with it.
claim_proof_invalid
401. The node key's signature over the claim token does not verify. Start again with a fresh enrolment.
checks_failed
422. A blocking check failed on the node. checks lists each result with its fix; fix them and send the claim again before the token expires.
node_exists
409. A live node already holds this host's fingerprint. Revoke that node first, then claim again.
supply_link_unavailable
503. The node's tunnel could not be set up; detail names the limit when one was hit. Retry after retry_after seconds. When owner_action_required is true, rent.dev has to act first.
node_revoked
410. The node is revoked for good. Enrol the machine again with rentdev-node up --re-enroll. A machine set up with a token made elsewhere holds no account key, and --re-enroll never makes one: make a new token there and run the same install line with it on stdin and --re-enroll added.
node_suspended
403. The node is suspended and may only send beats and events. Fix what rentdev-node doctor reports, then run it again. Once its checks pass, it asks for a probe itself.
node_replay
409. The node request reused a sequence number or nonce. Sign it again with a new one.
probe_in_progress
409. A probe of this node is already running. Wait for it to finish, then send the request again.
payout_proof_required
403. Changing payout details needs signed_nonce, signed by the account's agent key. Get a nonce from GET /v1/accounts/nonce, sign it and send the change again.
agent_upgrade_required
400. The node agent is older than the platform accepts. Run rentdev-node upgrade.
On the E2B-compatible paths
The E2B paths answer in E2B's own shape, {code, message}, so its SDKs can read them. A refusal from rent.dev carries the Problem code as error_code and keeps the Problem's extra members; see E2B compatibility.
Over MCP
A tool that is refused answers an isError result whose structured content is the same Problem; see the MCP server.