Skip to content
On this page

Errors

Look up a Probarion error by its code: what it means, what raised it, whether a retry helps and what to do next. Codes come from the vault contract, the SDK and the hosted app's HTTP routes.

LiveTestnetMainnetReferenceFor Developers35 min read.md (this page as Markdown)

Probarion reports a problem in one of these layers, and each layer has its own codes:

  • The vault contract refuses a call with a panic whose message is exactly PROBARION:<Code>. The whole call reverts.
  • The SDK throws errors that extend ProbarionError and carry .code. What the vault or the node answered about a spend comes back in the outcome's code instead.
  • The hosted app's HTTP routes answer with an HTTP status and a JSON body, { error, detail? }.

Every vault code and SDK error class has its own anchor, so you can link it, for example /docs/build/errors#NoMandate. Each HTTP row is anchored by its status and code, for example /docs/build/errors#http-404-not_found. The transaction failure codes and the unknown outcome codes are linked through their sections' anchors, Transaction failures and Unknown outcomes. SDK rule ids such as mandate.over_per_payment are not errors. They are the reasons a decision gives, and they are on Spend outcomes.

Where a code shows up#

The contract builds every refusal message in one place:

contracts/vault/src/errors.rs
Rust
    pub fn message(self) -> String {
        format!("PROBARION:{}", self.as_str())
    }

On NEAR, a panic undoes every state change the call made. The failed transaction stays on chain, and the code reaches you in one of these forms:

WhereWhat you see
An explorer, near-cli-rs or an RPC transaction statusSmart contract panicked: PROBARION:<Code>
process() in the SDKThe status refused_by_contract, with the bare code in code, such as DuplicateRef when another spend took the ref after the SDK read the vault. txHash is null when the check_spend dry run refused, and the failed transaction's hash when spend itself panicked.
checkSpend() in the SDKok: false and the bare code, with no PROBARION: prefix.
A ViewErrorprobarionCode, when the view call panicked with a vault code.
A ContractErrorvaultCode, and the same value in .code, when a transaction the SDK sent was refused, for example by VaultClient.anchor().
check in the CLIREFUSED: PROBARION:<Code> on the first line, and exit code 1.

The README's evaluation records this checkSpend() answer for 6 USDC on a mandate that allows at most 5 USDC per payment:

Text
6 USDC: { ok: false, code: 'OverPerPayment', would_hold: false }

A message without PROBARION: is not a vault code

A failure message without the PROBARION: prefix did not come from the vault's own checks. It came from the NEAR node, from near-sdk, or from a contract the vault called, such as the USDC token or NEAR Intents. For a spend it sent, the SDK names those failures with its own codes, under Transaction failures, and the near-sdk messages you may meet are under Messages that are not Probarion codes.

Read a code in your own code#

The SDK exports these helpers for vault codes and for the out-of-NEAR codes:

  • extractProbarionCode(value) reads the first PROBARION:<Code> in a string, an error or a nested RPC failure. It returns the bare code when it is a vault code, else null, even when a vault code comes later.
  • isVaultErrorCode(code) is true only for a code in VAULT_ERROR_CODES.
  • normalizeVaultCode(code) strips a PROBARION: prefix and checks nothing else, so test its result with isVaultErrorCode.
  • isOutOfNearCode(code) is true for LackBalanceForState and NotEnoughBalance.
codes.mjs
JavaScript
import {
  extractProbarionCode,
  isOutOfNearCode,
  isVaultErrorCode,
  normalizeVaultCode,
} from "./packages/sdk/dist/index.js";

console.log(extractProbarionCode("Smart contract panicked: PROBARION:NoMandate")); // NoMandate
console.log(extractProbarionCode("PROBARION:PayeeMismatch")); // null: not a vault code
console.log(normalizeVaultCode("PROBARION:Frozen")); // Frozen
console.log(isVaultErrorCode("LackBalanceForState")); // false
console.log(isOutOfNearCode("LackBalanceForState")); // true

The comments give what packages/sdk/src/errors.ts and packages/sdk/src/tx.ts return for these inputs. Save the file in the root of a clone built as Install shows, and run node codes.mjs there.

The CLI#

check asks the vault's free check_spend view and prints its answer on the first line. A refusal looks like this, and the command exits 1:

Text
REFUSED: PROBARION:OverPerPayment

Any other failure of the CLI prints error: <message> on stderr and exits 1. check and verify exit 64 for a usage error, so a bad flag never looks like a refusal or a failed check.

The CLI signs no owner or approver call. It checks the input, writes the arguments to a file and prints the near-cli-rs command. When the vault refuses that call, near-cli-rs shows Smart contract panicked: PROBARION:<Code>.

Vault error codes#

The table lists every code in VAULT_ERROR_CODES (packages/core/src/types.ts), in the contract's own order. The factory contract writes its refusals in the same format, with the same names.

  • Raised by names the methods that refuse with the code. "check n" is the n-th of the 14 spend checks that spend and check_spend run, in the order on How a payment is checked. When two checks would fail, the first one is the answer.
  • Retry helps is Yes when the same call, sent again unchanged after a wait, is expected to pass. No means something has to change first, such as the request, the signer or a mandate.
CodeMeaningRaised byRetry helpsWhat to do
NoMandateThe vault has no mandate with this id; the check_spend dry run reports it too.spend (check 4, and its payout), revoke_mandateNoUse a mandate id from the vault's mandate list; ids start at 1.
MandateInactiveThe mandate has been revoked, so it takes no new spend or approval; the check_spend dry run reports it too.spend (check 5), approve, revoke_mandate (on a revoked mandate)NoCreate a new mandate if this payee should still be paid (the owner signs).
MandateExpiredThe block time is at or past the mandate's expires_at_ns; the check_spend dry run reports it too.spend (check 6)NoCreate a new mandate with a later expiry (the owner signs).
NotMandateAgentThe signing key is one of the vault's agent keys, but not the agent_pk this mandate names; the check_spend dry run reports it too.spend (check 7)NoSign the spend with the agent key the mandate names.
ZeroAmountThe amount is 0; the check_spend dry run reports it too.spend (check 8)NoSend an amount above zero, written in the token's base units.
OverPerPaymentThe amount is above the mandate's max_per_payment; the check_spend dry run reports it too.spend (check 9)NoCheck the invoice amount, and if it is right, create a mandate with a higher cap (the owner signs).
UsesExhaustedThe mandate has been used max_uses times (a failed, rejected or expired spend gives its use back); the check_spend dry run reports it too.spend (check 10)NoWait for a held or pending spend of this mandate to be released, or create a new mandate (the owner signs).
OverMandateTotalThe mandate's spent and reserved amounts plus this amount would pass max_total (a failed, rejected or expired spend gives its reservation back); the check_spend dry run reports it too.spend (check 11)NoWait for a held or pending spend of this mandate to be released, or create a new mandate with room for this payment (the owner signs).
DuplicateInvoiceThis invoice_hash belongs to another spend that is held, pending, paid or burned; the check_spend dry run reports it too.spend (check 12)NoFind the spend that holds this invoice in the vault's spend list, and do not pay the invoice again.
DuplicateRefThe vault has already accepted a spend with this ref, and a ref stays used even when that spend later fails, is rejected or expires; the check_spend dry run reports it too.spend (check 13)NoFind the spend with this ref in the vault's spend list, and do not send the payment under a new ref until you know its status.
OverDailyBackstopThe vault's total for this UTC day, plus this amount, would pass the daily backstop; the check_spend dry run reports it too.spend (check 14)YesWait for the next UTC day, since the backstop is fixed when the vault is created and no method changes it.
FrozenThe owner has frozen the vault, so it takes no spend and no approval; the check_spend dry run reports it too.spend (check 3), approveYesAsk the owner to call unfreeze with exactly 1 yoctoNEAR attached (the owner signs).
NotAgentspend was called from an account other than the vault, or signed with a key that is not one of the vault's agent keys; the check_spend dry run reports the second case.spend (its caller check, and check 1)NoSign the spend on the vault account with one of its agent keys.
NotOwnerThe caller is not the vault's owner account.create_mandate, revoke_mandate, add_agent, remove_agent, set_ledger_key, freeze, unfreeze, withdraw, withdraw_intentsNoSend the call from the owner account (the owner signs).
NotApproverThe caller is not one of the vault's approvers.approve, rejectNoSend the call from one of the vault's approver accounts (the approver signs).
NotLedgerKeyanchor was not signed on the vault account with the vault's ledger key.anchorNoSign anchor on the vault account with the ledger key that set_ledger_key set.
NotHeldThere is no spend with this id, or the spend is not held.approve, reject, expire_heldNoRead the spend with get_spend to see its current status.
HoldExpiredapprove came after the spend's held_until_ns.approveNoRelease the spend with expire_held, which anyone may call, and submit the payment again with a new ref.
HoldNotExpiredexpire_held came at or before the spend's held_until_ns.expire_heldYesWait until held_until_ns has passed, then call expire_held again.
BadSeqThe anchor's seq is not the number of anchors so far plus 1.anchorNoRead the last anchor with list_anchors and anchor with the next seq, as the SDK does once by itself, and keep one ledger writer per vault.
AssetNotAllowedThe payee's asset is not in the vault's allowed_assets, or its prefix does not match the payee's chain; check_spend does not run this check.create_mandate, spend and approve (at payout)NoCreate the mandate with an asset from the vault's allowed_assets that matches the payee's chain (the owner signs).
InvalidInputAn argument is malformed or not allowed, for example a hash that is not 64 lowercase hex characters, a ref that is not 1 to 64 bytes, mandate limits that do not fit together, a zero amount or allowance, or a key the vault already holds (or, for remove_agent, does not hold); the check_spend dry run reports the spend case too.spend (check 2), create_mandate, add_agent, remove_agent, set_ledger_key, withdraw, withdraw_intents, anchor, new, the factory's create_vaultNoFix the argument the method refused and send the call again.
InsufficientDepositLess NEAR was attached than the call needs: for create_vault, the factory's min_deposit, plus the storage of the vault wasm when the current version is embedded; for create_mandate, the mandate's storage plus, for a NEAR payee, the payee's USDC storage registration.create_mandate, the factory's create_vaultNoFor create_vault, attach at least the min_deposit that the factory's get_config returns, plus the wasm's storage for an embedded version; for create_mandate, attach more NEAR, since the vault refunds the excess (the owner signs).
RequiresOneYoctoThe call did not attach exactly 1 yoctoNEAR, which only a full-access key can attach.unfreeze, withdraw, withdraw_intents, revoke_mandate, add_agent, remove_agent, set_ledger_key, approve, rejectNoSign with a full-access key and attach exactly 1 yoctoNEAR.

Owner signs

Several next actions on this page are owner transactions: create_mandate, unfreeze, and remove_agent then add_agent for an agent key. The CLI prints them and signs nothing, and the owner signs them from their own wallet. freeze takes no deposit. Most other owner methods need exactly 1 yoctoNEAR. create_mandate takes a storage deposit and refunds the excess.

The owner signs this transaction. Probarion never signs it.

Approver signs

An approver signs approve and reject from their own wallet, with exactly 1 yoctoNEAR attached. The CLI's spend approve and spend reject print the transaction and sign nothing.

An approver signs this transaction. Probarion never signs it.

With process(), many of these codes never reach the vault. The SDK's decide() mirrors most spend checks and refuses first, as refused_by_code with a rule id. Then process() asks check_spend before it sends anything. Spend outcomes lists the seven statuses process() returns. The order, the limits and the counters behind each check are on How a payment is checked and Mandates.

When the vault answers DuplicateRef or DuplicateInvoice#

A ref is used up once the vault accepts a spend, held or paid, and it stays used even if the payout fails. A refused spend reverts every change, so its ref stays free. An invoice_hash is taken only while a spend on it is held, pending, paid or burned.

process() refuses a used ref and a taken invoice by code first, with invoice.duplicate, so the vault answers DuplicateRef or DuplicateInvoice only when a spend with that ref or invoice landed after the SDK read the vault.

When the check_spend dry run answers the duplicate code, process() returns refused_by_contract with that code and txHash null at once, because nothing of this cycle was sent. When spend itself answers it, the spend that holds the ref or the invoice can be this cycle's own first copy, whose answer was lost. So for that answer the SDK does not report the code at once. It lists the vault's spends and looks for this decision's own spend, with the same ref, decision hash, invoice, mandate and amount:

What the SDK findsThe outcome
This decision's spend, paid, burned or heldThat status, with the spend's id.
This decision's spend, still pendingunconfirmed, with the code pending.
This decision's spend, released as failed, rejected or expiredfailed, with that status as the code.
Another decision's spend holds the ref, or holds the invoice liverefused_by_contract, with the duplicate code.
No spend holds it, or the list could not be readunconfirmed, with the duplicate code. It may have paid.

A spend that may have paid is never reported as refused or failed. To look a spend up yourself, read the vault's spend list: spends.get takes a spend id, not a ref, and the contract has no lookup by ref. Let an agent pay shows the lookup.

SDK errors#

Every error class the SDK exports extends ProbarionError, so one instanceof ProbarionError catches them all, and .code names the case. A subclass can share its parent's .code, so test the class with instanceof when the difference matters.

Class.codeWhenExtra fields
ProbarionError
extends Error
InvalidInputThe base class of every SDK error. The SDK also throws it with its own codes: InvalidInput (a malformed argument, refused before anything is read, sent or written), TxSendFailed (nothing was sent: the transaction could not be built or signed, or the time left the caller gave was too short, or could not be read, before it was signed or sent), TxFailed (the transaction result could not be read) and Internal (a failed internal consistency check, which a caller should report).code
RpcError
extends ProbarionError
RpcErrorA transport failure or a JSON-RPC error answer: every RPC URL failed, a node returned an error, or the time for the job ran out.attempts, rpcError
RpcMalformedError
extends RpcError
RpcErrorA node answered, but not in a shape the client can read. It is never a transport failure.None
ViewError
extends RpcError
RpcErrorA view call failed or returned an answer that is not the expected value; probarionCode is the vault code when the view panicked with one.contractId, methodName, probarionCode
ContractError
extends ProbarionError
TxFailedA transaction the SDK sent failed on chain, for example an anchor the vault refused (a refused spend is a spend outcome, not an error). .code is the vault code when there is one, the same value as vaultCode, and TxFailed otherwise.vaultCode, txHash
TxOutcomeUnknownError
extends ProbarionError
TxOutcomeUnknownThe transaction was signed and sent, but the node's answer was lost, so it may or may not have run. Record txHash, look the outcome up, and do not send the same payment again.txHash, signerId
TxRejectedError
extends ProbarionError
TxRejectedThe node refused the signed transaction before running it, so nothing changed. kind names the refusal, for example NotEnoughAllowance or AccessKeyNotFound.kind
ConfigError
extends ProbarionError
ConfigErrorAn option or a key the SDK needs is missing or malformed, or a client method got an argument it cannot send.None
NearAiError
extends ProbarionError
NearAiErrorThe model step failed: a missing API key, an HTTP error, a malformed answer, a missing attestation or no time left.None
NearAiResponseTooLargeError
extends NearAiError
NearAiErrorThe model's answer is larger than 64 KiB, so it is not used and the decision is rules-only.limitBytes
LedgerError
extends ProbarionError
LedgerErrorThe ledger store failed: an append onto another vault's ledger or onto a broken last entry, a line that is not valid UTF-8 or JSON, a lock it could not take, or a decision that landed at the wrong position (LEDGER_FORK_RISK).None
LedgerConflictError
extends LedgerError
LedgerErrorAnother writer moved the ledger's head since this append expected it, so nothing was written and no spend was sent.expected, actual

Thrown or returned#

process() returns an outcome, not an error, for everything the vault or the node answers about the spend: a refusal, a failed transaction and an unknown outcome are statuses. It throws when something is wrong before a spend can be sent:

  • ConfigError: the instance has no agent key or no ledger key, the agent key does not sign as the vault account, or the ledger key is not the vault's. It is also thrown when the agent's sender refuses the call as not set up: the decision entry is then written, and nothing is sent. The constructor throws it too for a model with no API key. Pass model: null to decide by code only.
  • ProbarionError with the code InvalidInput: an input it cannot use, for example a facts.invoice_hash that is not hashInvoice(text), or a facts.po_ref that is neither null nor a verbatim part of the text. Nothing is written.
  • RpcError or ViewError: a read of the vault failed.
  • LedgerConflictError: another writer moved the ledger since this decision was made. No entry was written and no spend was sent, and the SDK never retries it by itself.
  • LedgerError: the ledger store failed.
  • ProbarionError with the code Internal: a failed internal consistency check, which you should report. Nothing is written and nothing is sent.

Once spend is sent, process() does not throw: every answer becomes an outcome. That is inferred: it follows from the code, and no test shows it yet. These failures are not thrown at all:

  • A model step that fails is logged, and the cycle decides with the rules only.
  • A failed anchor is logged, and the outcome's anchorTxHash is null. The next cycle anchors the whole tail.
  • A payment entry that could not be written leaves the outcome as it is, with ledgerComplete: false.

Called directly, VaultClient.spend() throws where process() returns an outcome: a TxRejectedError when the node refused the signed transaction for any reason except the vault's NEAR balance, a ProbarionError with the code TxSendFailed when nothing was sent, and a TxOutcomeUnknownError when the outcome is not known. A vault refusal, and a node refusal for LackBalanceForState or NotEnoughBalance, come back as a value, with ok: false and the code.

Transaction failures#

These codes are not vault codes. process() returns them in the outcome's code, with the status failed, when the spend did not run or its own receipt failed:

CodeWhat happenedWhat to do
TxSendFailedThe SDK could not build or sign the transaction, so nothing was sent. This includes an agent key the vault account does not have: the SDK reads the key before it signs, and the message says the access key does not exist. The same code comes back when a sendTimeoutMs function gave too little time, or threw, before the transaction was signed or sent: nothing was sent then either.Fix what the message names, then run the cycle again. Sending again is safe. For a missing key, do what the AccessKeyNotFound row says.
NotEnoughAllowanceThe node refused the signed spend before it ran: the agent key's allowance is used up.The owner removes the key and adds it again with a new allowance: remove_agent, then add_agent.
AccessKeyNotFoundThe node refused it: the agent key is not on the vault account. A missing key usually shows up as TxSendFailed. This code appears when the key goes away between the SDK's read of it and the send.Have the owner add the key with add_agent. If the vault still lists it in list_agents, the owner first removes it with remove_agent, then adds it.
InvalidNonceThe node kept refusing the key's nonce, through several fresh signatures.Look for another process that signs with the same key, then run the cycle again.
Another refusal kindThe node refused the transaction for another reason, which the code names. Nothing ran.Read the message, fix the cause, then run the cycle again.
LackBalanceForStateThe chain refused the call: the vault account would fall below the NEAR its storage needs.Top the vault up with a plain NEAR transfer. The SDK's message says each paid spend keeps about 0.0048 NEAR of storage.
NotEnoughBalanceThe vault holds less NEAR than the spend must prepay for gas.Top the vault up with a plain NEAR transfer. The SDK's message puts the gas at about 0.02 NEAR for 200 Tgas.
TxFailedThe spend's own receipt failed without a vault code, for example with Exceeded the prepaid gas.Read the message, fix the cause, then run the cycle again.

The node refusals are the kinds of a TxRejectedError. In every row spendId is null: the vault did not accept the spend. For TxSendFailed and a node refusal nothing ran at all, so the ref is still free. For the out-of-NEAR codes and TxFailed, the chain refused the call or the spend's own receipt failed, and a failed receipt reverts like a refusal, so the ref stays free there too. That is inferred: it follows from the code, and no test shows it yet.

How a missing agent key shows up is inferred too. The SDK reads the key from the vault account before it signs, so a key the account does not have fails there, as TxSendFailed, and AccessKeyNotFound needs the key to go away after that read. With process(), a key the vault does not list never gets that far: it is refused by code when no mandate names it, and else the check_spend dry run answers NotAgent. The missing key process() can meet is one the vault still lists, for example after its key-adding receipt failed.

A failed outcome can also carry a spend status as its code, with spendId set. Then the vault accepted the spend and released it: the payout failed, or the spend the SDK found by ref was rejected or expired. Its ref is used up, so the same invoice needs a new ref.

Unknown outcomes#

These codes come with the status unconfirmed. The spend was sent, or may have been, and may have paid:

CodeWhat is not known
TxOutcomeUnknownThe spend was signed and sent, but the node's answer was lost, or a sender the SDK does not know failed in a way that may have sent it.
pendingThe vault accepted the spend, and its payout is still pending.
callback_failedThe spend's receipt ran and a later receipt failed, or the result does not show which one failed. The payout may have gone out.
unreadable_valueThe transaction succeeded, but its return value is not a spend result.
DuplicateRef, DuplicateInvoiceThe vault answered with a duplicate code, and no spend holding the ref or the invoice was found, or the spend list could not be read.

Never send an unconfirmed spend again

Do not send it under a new ref either. Find the spend by its ref in the vault's spend list, or wait. Until the chain shows the spend, or for 48 hours (UNKNOWN_SETTLE_MS), the SDK refuses the same invoice by code with ledger.unresolved.

HTTP API errors#

The hosted app's routes answer an error with a JSON body that is never cached:

  • the headers content-type: application/json; charset=utf-8 and cache-control: no-store;
  • the body { "error": "<code>" }, with a "detail" string when the route has more to say. A few rows add fields, which the table names.

For example, a request the rate limiter refuses gets this body:

JSON
{ "error": "rate_limited", "detail": "Try again in 12 s" }

A 429 from the shared rate limiter also sends a Retry-After header with the same number of seconds as its detail, Try again in N s. The faucet's daily limits answer 429 with a sentence of their own instead, and a Retry-After that runs to midnight UTC.

Who calls these routes#

The routes belong to the hosted app: its console, sign-in, top-up and proof files, among others. They are not an agent API.

  • The console routes need a signed-in wallet session.
  • The sign-in, sign-out, console, top-up and Canary routes that a page posts to check that the request comes from a page at the same address, and answer 403 bad_origin otherwise. The alert links' confirm and stop routes do not check it: the code or token from the alert email is the credential.
  • In the console routes, a vault that does not exist gets the same 403 forbidden as one you are not a member of, so a route never confirms a vault id. The faucet answers 404 not_found instead, for these, for a member who is not the owner and for a vault registered on the other network.

An agent pays from its own process, through the SDK. The CLI sends no spend: check only dry-runs one. See Let an agent pay.

On a testnet vault, test USDC comes from the faucet. Signed in as the vault's owner, open its Top-up tab (/console/<vault>/topup) and press the "Add test USDC" button. It mints 25 test USDC into the vault, and your wallet signs nothing: the team's mint-only key signs the mint. It works once a UTC day per vault, for up to 3 vaults per signed-in account a day. When the server has no faucet key, the tab shows instead: "Need test USDC? Send @probarionhq a direct message on X with your vault's name." The rows that name Top-up API (faucet) cover the faucet's own answers, such as not_owner and mint_failed. The faucet also answers 503 not_configured when the server's faucet key does not parse or is not a mint-only key.

StatusCodeReturned byMeaningWhat to do
400bad_code_formatExtension API (pairing)The pairing code is not 8 letters and digits.Enter the code exactly as the Browser extension page shows it, for example K7QM-4XRA.
400emptyConsole invoices API, Canary attempt APIThere is no text to work on: no text could be read from the invoice (a scanned PDF has no text layer), or the Canary attempt is blank.Paste the invoice text instead of the file, or type a Canary attempt that is not blank.
400invalid_amountTop-up API (quote)The top-up amount is not a USDC amount, or is not between 1 and 1000 USDC.Ask for a top-up of 1 to 1000 USDC, written as a plain decimal amount.
400invalid_inputConsole invoices API, Canary attempt API, Extension API, Top-up API, TEE check APIThe request body or query is malformed: a field is missing or has the wrong type, or the body is not the JSON or form the route reads.Send the fields the route expects, in the shape its detail names when there is one.
400too_longCanary attempt APIThe Canary attempt is longer than 4,000 characters.Shorten the text to 4,000 characters at most and try again.
400unreadableConsole invoices APIThe invoice file could not be read: it is empty or over 4 MiB, it is not the PDF it claims to be, the PDF could not be read in time, or the text file is not UTF-8.Upload a readable PDF or a UTF-8 text file, or paste the invoice text.
401bad_codeExtension API (pairing)The pairing code is wrong, used or expired.Show a new code on the Browser extension page and enter that one.
401bad_signatureSign-in APIThe wallet's signature does not verify over the sign-in challenge, or its public key is not a full-access key of the account.Sign in again with a full-access key of the account.
401bad_tokenExtension APIThe extension sent no token, or a token that is unknown, expired, revoked or made at the other network's address.Connect the extension again: open Probarion, then Browser extension.
401challenge_missing_or_expiredSign-in APIThe sign-in challenge is missing, expired or already used.Start the sign-in again, so the server issues a fresh challenge.
401invalid_inputSign-in APIThe signed login is malformed: the account id, the public key or the signature is missing or not in its expected form.Sign in again from the wallet prompt, without changing what the wallet sends.
401unauthenticatedConsole invoices API, Top-up APIThere is no signed-in session at this address.Sign in with your NEAR wallet and send the request again.
401unauthorizedCron routes, Telegram webhookThe call did not carry the route's secret: the cron bearer secret, or the Telegram webhook secret.Leave these routes to the scheduler and to Telegram, which hold their secrets.
403bad_originSign-in API, Console invoices API, Canary attempt API, Top-up API, TEE check APIThe request's Origin header is missing, or is not the address the request came in at. For the TEE check, the browser said in Sec-Fetch-Site that another site's page made the call.Send the request from a Probarion page at this address.
403forbiddenConsole invoices API, Top-up APIThe signed-in account is not a member of this vault with a role that may do this; a top-up quote also needs the vault's owner on chain.Sign in with an account that has the needed role on this vault.
403not_memberExtension API (queue an invoice)The token's account is not an owner or an approver of this vault (a vault that does not exist gets the same answer), or the vault is a Canary vault, which takes no invoices from the extension; nothing was stored.Choose a vault where the connected account is an owner or an approver, and not a Canary vault.
404mandate_not_foundExtension API (queue an invoice)The vault's mandates, as the chain lists them now, have no mandate with this id; nothing was stored.Choose a mandate that the extension lists for this vault.
404not_foundProof files (snapshot.json, ledger.jsonl, payments.csv), Top-up API (faucet)There is no proof to give: the vault id is not a NEAR account id, nobody registered the vault, or its proof page is not public and you are not a member. The faucet answers it at any address but testnet's, and to anyone but the vault's owner, so a vault id is not confirmed.Check the vault id, or sign in as a member of the vault if its proof page is not public; for the faucet, sign in as the vault's owner at the testnet address.
409asset_not_allowedTop-up API (quote)The vault does not allow Base USDC, so a top-up could not pay a Base payee from it.Top up a vault whose allowed_assets include Base USDC, since they are fixed when the vault is created.
409busyConsole invoices API, Canary attempt APIAnother invoice for this vault, or another Canary attempt, is being processed.Wait until the other run has finished, then send it again: an invoice upload can take up to 90 s and a Canary attempt up to 80 s.
409duplicateConsole invoices APIThe vault already has this invoice: the same text once normalised, or this text again after custom.invoice_number_duplicate refused it while the number is still blocked. The body adds invoiceId and status. Another text with the number of an invoice that was paid or may still pay is not a 409: its cycle runs and that rule refuses it, and when the rule's refusal is the outcome's code the answer adds a notice.Read the invoice's status instead of sending it again. A paid invoice is not paid again. A text the number rule refused runs again only once no invoice that may pay has the number, for example after the owner rejects the earlier invoice in the console while it waits for the owner. A refused text whose refusal could not be written answers this 409 with status processing whatever happens to the earlier invoice, and its number stays blocked. An approver's rejection of a held spend keeps the number blocked: the console does not yet free a number when that spend fails, is rejected or expires.
409key_unavailableConsole invoices APIThe mandate's agent key is not active in this console, so nothing was sent.Activate that key on the Keys tab, or create the mandate for an active key (the owner signs).
409mainnet_onlyTop-up APINEAR Intents and 1Click exist on mainnet only, so a testnet vault has no top-up.On testnet, press "Add test USDC" on the vault's Top-up tab instead.
409no_keysConsole invoices API, Extension API (queue an invoice)The vault has no active agent key, or no active ledger key, in this console; for the extension, the agent key must be the one the chosen mandate names.Activate the missing key on the Keys tab (the owner signs).
409no_mandateConsole invoices APINo purpose document was attached, or no mandate of this vault has the attached document's hash as its purpose_hash.Attach the purpose document (the PO or contract) you hashed when you created the mandate.
409not_ownerTop-up API (faucet)The chain names another account than the signed-in one as the vault's owner, so nothing was minted.Sign in with the account the chain names as the vault's owner.
409wrong_networkConsole invoices API, Extension API (queue an invoice), Top-up APIThe vault is on the other network than the address the request came in at.Open the vault at its own network's address.
409wrong_tokenTop-up API (faucet)The vault's token is not testnet's USDC, so the faucet's test USDC would not count in it, and nothing was minted.Use the faucet on a vault made for testnet's USDC; a vault's token is set when it is created.
411length_requiredConsole invoices API, Extension API (queue an invoice)The upload has no valid Content-Length header.Send the upload with a Content-Length header, as a browser form does.
413payload_too_largeSign-in APIThe sign-in body is larger than 2 KiB, which no signed login is.Send only the signed login the wallet returned.
413too_largeConsole invoices API, Extension API (queue an invoice)The upload is too large: the invoice or the purpose document is over 4 MiB, or the whole request is over 4 MiB plus 64 KiB (4 MiB plus 16 KiB for the extension, which sends no purpose document).Send a smaller file, or paste the invoice text in the console instead.
415unsupportedConsole invoices API, Extension API (queue an invoice)The invoice file is not a PDF or a plain text file.Send the invoice as a PDF or a plain text (.txt) file, or paste its text in the console instead.
422amount_unclearExtension API (queue an invoice)The code could not read one clear USDC total from the invoice: the text has no total it can read, has totals that disagree, shows a zero total or another currency, is cut short, or is not a payable invoice; nothing was stored.Upload the invoice in the console instead, or send an invoice that states one clear total.
422emptyExtension API (queue an invoice)There is no text in the file (a scanned PDF has no text layer, or the text file is blank); nothing was stored.Upload the invoice in the console instead, where you can paste its text.
422mandate_inactiveExtension API (queue an invoice)The chosen mandate cannot take an invoice now: it is revoked or expired, has no uses or no total left, has a status, expiry, use count or total the code cannot read, or has a payee the owner's confirmation message cannot name; the detail names the mandate and the reason, and nothing was stored.Choose another mandate of this vault, or create a new one for this payee (the owner signs).
422refused_by_codeExtension API (queue an invoice)The code refused the invoice, and the body adds rule: mandate.payee_mismatch when the payee the invoice names contradicts the mandate's payee, or contract.check_spend when the vault's free check_spend view says the vault would refuse this payment now (the detail names the contract's code, for example DuplicateInvoice); nothing was stored.Choose the mandate that pays the payee on the invoice, or look up the contract code in detail in the vault error codes and fix what it names.
422unreadableExtension API (queue an invoice)The invoice file could not be read: it is sent as a PDF but is not one, the PDF could not be read or took too long, or the text file is not UTF-8; the detail says which, and nothing was stored.Send a readable PDF or a UTF-8 text file, or upload the invoice in the console instead.
429budgetCanary attempt APIThe Canary's budget is used up for now: the day's model token budget, or the attempts allowed in total or from this address.Wait the seconds in the Retry-After header, then try again.
429rate_limitedSign-in API, Console invoices API, Canary attempt API, Top-up API, Extension API, TEE check API, proof files, alert confirm link, Telegram webhookToo many requests in the route's window; the answer carries Retry-After and the detail Try again in N s.Wait the seconds in the Retry-After header before you send the request again.
500internalConsole invoices APIThe invoice pipeline returned a result the route does not know, which is a bug.Report it, and read the vault's invoices and spends before you upload the invoice again.
502failedConsole invoices API, Canary attempt APIThe cycle stopped before any payment was sent, or the Canary attempt ran out of time; the invoice or the attempt is stored as an error.Upload the invoice again, or send a new Canary attempt.
502mint_failedTop-up API (faucet)The mint reached NEAR and the token refused it, so no test USDC arrived and the vault's day is used; the body adds txHash.Send @probarionhq a direct message on X with your vault's name and the txHash.
502quote_rejectedTop-up API (quote)1Click's quote does not match what was asked for, so it is not used.Ask for a new quote.
502quote_unavailableTop-up API (quote)1Click could not give a quote.Ask for a quote again in a minute.
502status_unavailableTop-up API (status)1Click could not report the deposit's status.Ask for the status again later, since 1Click also finds the deposit by itself.
503chain_unavailableConsole invoices API, Extension API (queue an invoice), Top-up API (quote)The vault could not be read from NEAR, so nothing was stored or sent.Try again when the NEAR RPC answers.
503closedCanary attempt APIThe Canary takes no attempts (its mode is off or replay), or its ledger is full.Try the Canary again once it is open.
503key_unavailableConsole invoices APIA key cannot be opened on the server, so nothing was sent; the operator is alerted.Try again later, once the operator has fixed the key.
503not_configuredTop-up API, Telegram webhookThis deployment has not set up the service the route needs: 1Click quotes for top-ups, or the Telegram bot.Ask the deployment's operator to set the service up, since the request itself is fine.
503not_readyCanary attempt APIThe Canary is not ready on this network: its vault, model key, mandate, keys or ledger key are not usable, or the chain did not answer in time.Try the Canary again later.
503unavailableSign-in API, Console invoices API, Canary attempt API, Top-up API, Extension API, TEE check API, proof files, alert links, cron routes, Telegram webhookSomething the route depends on failed (the database, a server key, a setting or the chain), and the route answers this instead of an unhandled error.Try again in a moment, and quote the request id from the detail when you report it.
503wrong_chainSign-in APIAn RPC address set for this network answers for the other chain, so no sign-in is accepted.Tell the deployment's operator, since the fault is in its RPC setting.

Messages that are not Probarion codes#

MessageWhere it comes fromWhat it means
Method <name> is privatenear-sdk, on the vault's payout callbacks on_transfer and on_withdraw, and on the factory's callback on_vault_createdOnly the contract itself may call its callbacks. Any other caller gets this message.
Method <name> doesn't accept depositnear-sdk, on freeze, spend, anchor, expire_held, the payout callbacks, the new init of the vault and the factory, and the factory's on_vault_createdThese methods refuse any attached deposit. View methods have no such guard. For spend the node refuses first, because the agent's function-call key cannot attach a deposit.
PayeeMismatchThe SDK's rule mandate.payee_mismatch, off chainIt is not a contract code. spend has no address field, so the vault has no payee to compare. The SDK refuses by code, as refused_by_code, when the invoice or the model names a payee that contradicts the mandate's. See Why spend has no payee.

Built from 4ab41ca · reviewed

Show

Loading the search index