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.

View as Markdown

The shape of a Problem

JSON
{
  "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."
    }
  ]
}
MemberTypeDescription
typestringRequired. URI identifying the problem type.
titlestringRequired.
statusinteger, 100 to 599Required.
codeinsufficient_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_requiredRequired. Stable machine-readable error code.
detailstring
instancestring
request_idstring
docs_urlstring
balance_required_microsintegerAdditional balance, in micro-USD, that would let the request succeed.
hold_idstringhold_ followed by a 26-character ULID.
retry_afterinteger, at least 0Seconds to wait before retrying; mirrors the Retry-After header.
topupTopupLinks
errorsarray of objectPer-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

CodeStatusTitle
insufficient_balance402Insufficient balance
account_frozen402Account frozen
key_limit_reached402Key spend limit reached
payment_required402Payment required
payment_failed402Payment failed
unsupported_parameter400Unsupported parameter
invalid_request400Invalid request
unauthenticated401Authentication required
forbidden403Forbidden
not_found404Not found
method_not_allowed405Method not allowed
conflict409Conflict
idempotency_in_flight409Request with this Idempotency-Key in flight
gone410Gone
idempotency_key_reused422Idempotency-Key reused with a different payload
rate_limited429Rate limited by the vendor
internal_error500Internal error
not_implemented501Not implemented
vendor_error502Vendor error
no_capacity503No capacity
vendor_timeout504Vendor timeout
claim_invalid410Claim token used or expired
claim_proof_invalid401Claim proof does not verify
checks_failed422A blocking check failed
node_exists409Host already enrolled as a node
supply_link_unavailable503Node link unavailable
node_revoked410Node revoked
node_suspended403Node suspended
node_replay409Node request replayed
probe_in_progress409Probe in progress
payout_proof_required403Payout change needs a signed nonce
agent_upgrade_required400Node 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.

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.