Docs
v1

Reference

Errors

The error document of the Tenrai API, its codes and HTTP statuses, which failures to retry, and the messages a rejected transaction gets.

On this page

Error document

Every failure answers with the same JSON document:

JSON
{
  "api_version": 1,
  "code": "unavailable",
  "message": "the node is busy; retry shortly",
  "retry_after_millis": 250
}
FieldMeaning
codeStable category for programs, see below
messageOne line of plain text for people, at most 512 bytes. Do not parse it
retry_after_millisSet only when a retry makes sense

Codes

HTTPcodeWhenRetry
400invalid_requestInvalid input, or a transaction the rules rejectNo
403invalid_requestA web page whose origin is not admittedNo
404not_foundUnknown recordNo
409conflictAlready pooled, or an input is spent or unknownNo
429rate_limitedToo many requests or sockets from one addressAfter retry_after_millis
503unavailableBusy, still loading, low on disk, or the mempool is fullAfter retry_after_millis
500internalThe service could not answerNo

Some refusals happen before a route runs and carry no document, only the status:

HTTPWhen
404Unknown route
405Wrong method
413Body over 128 KiB
415Body without content-type: application/json
422JSON of the wrong shape, an unknown field, or an api_version other than 1

The same goes for a 502 or 504 from a proxy in front of the service. Check the status before you parse the body.

Retrying

  • Reads: repeat after 429 and 503, waiting retry_after_millis. A read with no answer may be repeated after a short pause.
  • Submissions: repeat after 429 and 503 only. After a lost answer, a timeout or a proxy error, ask GET /v1/transactions/{id}/status first. The transaction ID is known before you submit.
  • 409 on a submission usually means the transaction is already in the mempool. Read its status.

Submitting the same signed transaction twice is harmless: it has one ID and can execute once.

Transaction rejections

MessageMeaning
the fee is below the minimum for the transaction massRaise the fee to at least minimum_fee_per_mass × mass
the outputs exceed the inputsThe inputs do not cover outputs plus fee
an input is not in the finalized UTXO set409. The output is spent, or not final yet
an input is already spent by a pooled transaction409. Another pending transaction uses it
the transaction is already pooled409. Nothing to do
an input authorization is invalidA signature or key does not match the output's lock
the transaction is bound to different chain rulesBuilt for another chain, version or rule set. Read the manifest again
the transaction validity interval has not opened yetvalid_from lies ahead of the finalized head
the transaction validity interval has expiredBuild and sign it again
finalized state moved; resubmit the transaction503. Send the same bytes again
the mempool is full; retry with a higher fee later503

Staking rejections

MessageMeaning
the stake is below the minimum delegation …Stake at least minimum_delegation
the validator does not take new stakeThe validator is not open for stake, for example because it is leaving
the validator does not exist, the stake position does not existWrong ID
the validator or position changed since it was read …Read the record again and rebuild

On sockets

A refused frame comes back as an error frame that wraps the same document:

JSON
{
  "type": "error",
  "data": {
    "id": 5,
    "error": {
      "api_version": 1,
      "code": "invalid_request",
      "message": "the transaction topic needs exactly one transaction_id",
      "retry_after_millis": null
    }
  }
}

Type to search guides, concepts and reference pages.