Errors
Every error the API can return: the Problem Details envelope, how to handle it, and the full catalog of stable error codes.
Every non-2xx response — REST and GraphQL alike — speaks one error language. REST returns an RFC 9457 Problem Details object; GraphQL carries the same code vocabulary in errors[].extensions.code.
{
"type": "https://docs.trustlesswork.com/trustless-work/v2-en/api-rest/errors/escrow-not-found",
"title": "Not Found",
"status": 404,
"code": "ESCROW_NOT_FOUND",
"detail": "Escrow does not exist.",
"instance": "/escrow/single-release/v2/fund-escrow",
"traceId": "d0f1…"
}How to handle errors
Switch on
code. It is stable and never renamed.detailis human prose and may change without notice.typeis a link to that code's page in this section.extensionscarries machine-readable context where it helps:extensions.errors[]on validation failures,extensions.restoreXdronSTELLAR_STATE_ARCHIVED,extensions.missing[]onESCROW_RECEIVER_TRUSTLINE_MISSING,extensions.tokenContractIdon token contract errors.Include
traceIdwhen reporting a problem — it correlates your request with the server logs.
Escrow contract errors
Raised when the on-chain simulation of a build endpoint fails inside the escrow contract. They are grouped by the lifecycle phase where you will most likely hit them — note that a few codes can surface in more than one operation.
Deploy, update & configuration
Invalid roles, milestones or properties when deploying or updating an escrow.
ESCROW_ADMIN_ADDRESS_CANNOT_BE_CHANGED
422
Admin address cannot be changed after initialization.
ESCROW_ADMIN_ADDRESS_OVERLAPS_WITH_OTHER_ROLE
422
Admin address must not overlap with any other role.
ESCROW_ALREADY_INITIALIZED
409
Escrow is already initialized.
ESCROW_AMOUNT_CANNOT_BE_ZERO
422
Amount must be greater than zero.
ESCROW_APPROVERS_LIST_EMPTY
422
roles.approvers must contain at least one address.
ESCROW_DISPUTE_RESOLVERS_LIST_EMPTY
422
roles.dispute_resolvers must contain at least one address.
ESCROW_DISPUTE_RESOLVER_OVERLAPS_WITH_OTHER_ROLE
422
A dispute resolver cannot also appear in another role.
ESCROW_DUPLICATE_ADDRESS_IN_ROLE
422
A role list contains duplicate addresses.
ESCROW_FLAGS_MUST_BE_FALSE
422
Escrow flags (approved, disputed, released) must all be false for this action.
ESCROW_HAS_FUNDS
409
Escrow still holds funds; action blocked.
ESCROW_INCOMPATIBLE_WASM_HASH
422
Target contract is not an instance of the expected escrow type.
ESCROW_MILESTONE_APPROVED_CANT_CHANGE_PROPERTIES
409
Escrow properties cannot be modified after a milestone approval.
ESCROW_NO_MILESTONE_DEFINED
422
Escrow has no milestones defined.
ESCROW_PLATFORM_ADDRESS_CANNOT_BE_CHANGED
422
Platform address cannot be modified.
ESCROW_PLATFORM_FEE_TOO_HIGH
422
Platform fee cannot exceed 99%.
ESCROW_PROPERTIES_MISMATCH
409
Provided escrow properties do not match the on-chain state.
ESCROW_RELEASE_SIGNERS_LIST_EMPTY
422
roles.release_signers must contain at least one address.
ESCROW_ROLE_LIMIT_EXCEEDED
422
A role list exceeded its maximum size (5 addresses per list).
ESCROW_SERVICE_PROVIDERS_LIST_EMPTY
422
roles.service_providers must contain at least one address.
ESCROW_STRING_TOO_LONG
422
A String field exceeded its on-chain maximum length.
ESCROW_TARGET_CANNOT_BE_ZERO
422
A milestone approvals.target must be greater than zero.
ESCROW_TARGET_EXCEEDS_APPROVERS
422
A milestone approvals.target cannot exceed roles.approvers.length.
ESCROW_TOO_MANY_MILESTONES
422
Too many milestones; the maximum is 50.
ESCROW_TOTAL_AMOUNT_CANNOT_BE_ZERO
422
Total amount cannot be zero.
Funding
ESCROW_INSUFFICIENT_FUNDS_FOR_FUNDING
409
Insufficient funds to fund the escrow.
ESCROW_NOT_FUNDED
409
Escrow has not been funded yet.
Milestones & approvals
Changing milestone status, approving milestones, and managing the milestone list.
ESCROW_APPROVER_ALREADY_APPROVED_MILESTONE
409
This approver already approved this milestone.
ESCROW_BATCH_MILESTONE_APPROVE_EMPTY
422
approve_milestones batch cannot be empty.
ESCROW_BATCH_MILESTONE_UPDATE_EMPTY
422
change_milestone_status batch cannot be empty.
ESCROW_BATCH_TOO_LARGE
422
Milestone batch exceeded the maximum size of 50 entries.
ESCROW_DUPLICATE_MILESTONE_INDEX
422
Duplicate milestone indices are not allowed in the batch.
ESCROW_EMPTY_MILESTONE_STATUS
422
Milestone status cannot be empty.
ESCROW_INVALID_MILESTONE_INDEX
422
Milestone index is out of range.
ESCROW_MILESTONE_HAS_ALREADY_BEEN_APPROVED
409
Milestone was already approved.
ESCROW_MILESTONE_NOT_COMPLETED
409
Milestone is not completed; action cannot proceed.
ESCROW_MILESTONE_NOT_FOUND
404
Milestone does not exist.
ESCROW_MILESTONE_TO_APPROVE_DOES_NOT_EXIST
404
Milestone to approve does not exist.
ESCROW_MILESTONE_TO_UPDATE_DOES_NOT_EXIST
404
Milestone to update does not exist.
ESCROW_MILESTONE_UPDATE_NOT_ALLOWED_WITH_FUNDS
409
Milestones cannot be edited while the escrow holds funds.
Disputes & resolution
Opening disputes and distributing funds when resolving them.
ESCROW_ALREADY_IN_DISPUTE
409
Escrow is already in dispute.
ESCROW_ALREADY_RESOLVED
409
Escrow dispute is already resolved.
ESCROW_AMOUNTS_TO_TRANSFER_SHOULD_BE_POSITIVE
422
Transfer amounts must be positive.
ESCROW_APPROVER_OR_RECEIVER_FUNDS_LESS_THAN_ZERO
422
Approver or receiver funds cannot be negative.
ESCROW_BATCH_MILESTONE_DISPUTE_EMPTY
422
dispute_milestones requires at least one milestone index.
ESCROW_DISTRIBUTIONS_MUST_EQUAL_BALANCE
422
Distributions must equal the total escrow balance.
ESCROW_INSUFFICIENT_FUNDS_FOR_RESOLUTION
409
Insufficient funds to resolve the dispute.
ESCROW_MILESTONE_ALREADY_DISPUTED
409
Targeted milestone is already in dispute.
ESCROW_MILESTONE_ALREADY_IN_DISPUTE
409
Milestone is already in dispute.
ESCROW_MILESTONE_ALREADY_RESOLVED
409
Milestone dispute is already resolved.
ESCROW_MILESTONE_NOT_IN_DISPUTE
409
Milestone is not currently in dispute.
ESCROW_MILESTONE_OPENED_FOR_DISPUTE_RESOLUTION
409
Milestone is opened for dispute resolution; action blocked.
ESCROW_NOT_IN_DISPUTE
409
Escrow is not currently in dispute.
ESCROW_OPENED_FOR_DISPUTE_RESOLUTION
409
Escrow is opened for dispute resolution; action blocked.
ESCROW_RECEIVER_AND_APPROVER_FUNDS_NOT_EQUAL
422
Receiver and approver distributions do not match.
ESCROW_TOO_MANY_DISTRIBUTIONS
422
Too many distributions; the maximum is 50.
ESCROW_TOTAL_DISPUTE_FUNDS_MUST_NOT_EXCEED_MILESTONE_AMOUNT
422
Total dispute funds cannot exceed the milestone amount.
Release, withdraw & refunds
ESCROW_ALREADY_RELEASED
409
Escrow funds were already released.
ESCROW_BALANCE_NOT_ENOUGH_TO_SEND_EARNINGS
409
Escrow balance is insufficient to release the earnings.
ESCROW_CANT_RELEASE_A_MILESTONE_IN_DISPUTE
409
Cannot release a milestone that is in dispute.
ESCROW_INSUFFICIENT_APPROVER_FUNDS_FOR_COMMISSIONS
409
Approver has insufficient funds for commissions.
ESCROW_INSUFFICIENT_ESCROW_FUNDS_TO_MAKE_REFUND
409
Insufficient escrow funds to make the refund.
ESCROW_INSUFFICIENT_FUNDS_FOR_REFUND
409
Insufficient funds for refund.
ESCROW_INSUFFICIENT_SERVICE_PROVIDER_FUNDS_FOR_COMMISSIONS
409
Service provider has insufficient funds for commissions.
ESCROW_MILESTONE_ALREADY_RELEASED
409
Milestone funds were already released.
ESCROW_NOT_COMPLETED
409
Escrow has pending milestones; action cannot proceed.
ESCROW_NOT_FULLY_PROCESSED
409
Escrow has not been fully processed.
ESCROW_RELEASE_MILESTONES_EMPTY
422
release_funds requires at least one milestone index.
Roles: who can do what
The signing wallet does not hold the role the action requires. Check the escrow's roles with a read endpoint before building the transaction.
ESCROW_DISPUTE_RESOLVER_CANNOT_DISPUTE
403
The dispute resolver cannot initiate a dispute.
ESCROW_DISPUTE_RESOLVER_CANNOT_DISPUTE_MILESTONE
403
The dispute resolver cannot initiate a dispute on a milestone.
ESCROW_ONLY_ADMIN_CAN_EXECUTE
403
Only the admin address can perform this action.
ESCROW_ONLY_APPROVER_CAN_CHANGE_MILESTONE_FLAG
403
Only the approver can change the milestone approval flag.
ESCROW_ONLY_DISPUTE_RESOLVER_CAN_EXECUTE
403
Only the dispute resolver can perform this action.
ESCROW_ONLY_PLATFORM_ADDRESS_CAN_EXECUTE
403
Only the platform address can perform this action.
ESCROW_ONLY_RELEASE_SIGNER_CAN_RELEASE
403
Only the designated release signer can release funds.
ESCROW_ONLY_SERVICE_PROVIDER_CAN_CHANGE_MILESTONE_STATUS
403
Only the service provider can change a milestone status.
ESCROW_SIGNER_MUST_BE_APPROVER_AND_RELEASE_SIGNER
403
The signer must be in both approvers and release_signers.
ESCROW_UNAUTHORIZED_APPROVER
403
Caller is not in roles.approvers.
ESCROW_UNAUTHORIZED_TO_CHANGE_DISPUTE_FLAG
403
Caller is not authorized to change the dispute flag.
Lookup & arithmetic
Cross-cutting: the escrow does not exist, or an amount overflowed on-chain.
ESCROW_DIVISION_ERROR
500
Arithmetic division error while processing the escrow.
ESCROW_NOT_FOUND
404
Escrow does not exist.
ESCROW_OVERFLOW
500
Arithmetic overflow while processing the escrow.
ESCROW_REENTRANCY
500
Reentrant call detected.
ESCROW_TOO_MANY_ESCROWS_REQUESTED
422
Too many escrows requested; the maximum is 20 per call.
ESCROW_UNDERFLOW
500
Arithmetic underflow while processing the escrow.
Token contract errors
Raised when the on-chain simulation of a build endpoint fails inside the escrow's token contract (the trustline asset) rather than the escrow itself — for example a fund signer with no trustline for the asset. extensions.tokenContractId names the token that raised it.
TOKEN_ACCOUNT_MISSING
422
The Stellar account does not exist on this network.
TOKEN_ACCOUNT_NOT_CLASSIC
422
The address is not a classic Stellar account.
TOKEN_ALLOWANCE_ERROR
409
The token allowance is insufficient or invalid.
TOKEN_ALREADY_INITIALIZED
409
The token contract is already initialized.
TOKEN_AUTHENTICATION_ERROR
403
The token contract could not authenticate the invocation.
TOKEN_BALANCE_DEAUTHORIZED
403
The asset issuer deauthorized the trustline.
TOKEN_BALANCE_INSUFFICIENT
409
The token balance is insufficient for this operation.
TOKEN_INTERNAL_ERROR
500
The token contract failed with an internal error.
TOKEN_NEGATIVE_AMOUNT
422
Token amounts must not be negative.
TOKEN_OPERATION_NOT_SUPPORTED
422
The token contract does not support this operation.
TOKEN_OVERFLOW
500
Arithmetic overflow inside the token contract.
TOKEN_TRUSTLINE_MISSING
422
The account has no trustline for the escrow token, or does not exist yet.
TOKEN_UNAUTHORIZED
403
The token contract rejected the caller as unauthorized.
API errors
Raised by the API itself before anything touches the chain.
Authentication, API keys & sessions
API_KEY_LIMIT_REACHED
409
You have reached the maximum number of active API keys.
AUTH_BOOTSTRAP_ALREADY_DONE
409
An admin already exists.
AUTH_BOOTSTRAP_EMAIL_TAKEN
409
A user with that email already exists.
AUTH_BOOTSTRAP_INVALID_SECRET
401
Invalid bootstrap secret.
AUTH_BOOTSTRAP_SECRET_NOT_CONFIGURED
422
Bootstrap is disabled on this deployment.
AUTH_CREDENTIAL_MISSING
401
The request carries no API key or session token.
AUTH_INSUFFICIENT_ROLE
403
The credential does not have permission for this operation.
AUTH_INVALID_CREDENTIAL
401
Invalid API key or session token.
AUTH_INVALID_FORMAT
401
Invalid API key format.
AUTH_KEY_EXPIRY_IN_PAST
422
expiresAt must be in the future.
AUTH_KEY_EXPIRY_TOO_FAR
422
Requested key expiry exceeds the maximum lifetime.
AUTH_KEY_NOT_FOUND
404
API key not found.
AUTH_KEY_NO_ROLES
422
At least one role is required.
AUTH_ROLE_CEILING
403
Cannot grant a role higher than your own.
AUTH_SESSION_BAD_ALG
401
The JWT declares an unexpected signing algorithm.
AUTH_SESSION_BAD_SIGNATURE
401
The JWT signature does not verify.
AUTH_SESSION_EXPIRED
401
The session token is past its expiry.
AUTH_SESSION_INVALID
401
The JWT payload fails validation.
AUTH_SESSION_MALFORMED
401
The bearer token is not a parseable JWT.
AUTH_SESSION_NOT_CONFIGURED
422
Wallet-session auth is not configured on the server.
AUTH_SESSION_REVOKED
401
Session has been revoked. Sign in again.
AUTH_SESSION_UNAVAILABLE
401
Session auth is not enabled on this server.
AUTH_USER_ID_INVALID
422
userId must be a valid identifier.
AUTH_USER_INACTIVE
422
Cannot create API keys for inactive users.
AUTH_USER_NOT_FOUND
404
User not found.
Wallet auth: registration, login & recovery
SEP-10 challenge flows. Challenges are single-use and short-lived: always request a fresh one, sign it with the exact wallet, and submit it unmodified.
RECOVERY_BAD_SIGNATURE
403
Signature does not prove ownership of the address.
RECOVERY_CHALLENGE_REUSED
403
This challenge has already been used.
RECOVERY_KEY_LIMIT_REACHED
409
This account is at its active API-key limit.
RECOVERY_WALLET_NOT_REGISTERED
404
No registered account is linked to this wallet.
REGISTRATION_BAD_SIGNATURE
403
Signature does not prove ownership of the address.
REGISTRATION_CHALLENGE_REUSED
403
This challenge has already been used.
REGISTRATION_CLOSED
403
Self-registration is disabled.
REGISTRATION_EMAIL_TAKEN
409
A user with that email already exists.
REGISTRATION_WALLET_TAKEN
409
This wallet is already registered.
SESSION_BAD_SIGNATURE
403
Signature does not prove ownership of the address.
SESSION_CHALLENGE_REUSED
403
This challenge has already been used.
SESSION_USER_INACTIVE
403
This account is deactivated.
SESSION_WALLET_NOT_REGISTERED
404
No registered account is linked to this wallet.
WALLET_BAD_SIGNATURE
403
Signature does not prove ownership of the address.
WALLET_CANNOT_REMOVE_LAST
409
You cannot remove your last verified wallet.
WALLET_CHALLENGE_EXPIRED
422
The challenge has expired. Request a new one.
WALLET_LINK_NOT_FOUND
404
No wallet-link challenge found.
WALLET_NOT_FOUND
404
No such wallet is linked to your account.
WALLET_OWNED_BY_OTHER
422
This address is already linked to another account.
Users, platforms & subjects
PLATFORM_ID_INVALID
422
platformId must be a numeric string.
PLATFORM_NOT_FOUND
404
Platform not found for this account.
PLATFORM_REQUIRED
422
This account has no active platform for this operation.
SUBJECT_EXTERNAL_ID_TAKEN
409
Another subject of this platform already uses that externalId.
SUBJECT_NOT_FOUND
404
Subject not found under this platform.
USER_EMAIL_TAKEN
409
A user with that email already exists.
USER_ID_INVALID
422
userId must be a valid identifier.
USER_NOT_FOUND
404
User not found.
USER_NO_ROLES
422
At least one role is required.
Request validation
AMOUNT_INVALID
422
amount is too large to be represented exactly.
AMOUNT_OUT_OF_RANGE
422
amount is larger than the maximum on-chain value (i128).
AMOUNT_PRECISION_UNSUPPORTED
422
An amount has more decimal places than the asset supports.
ESCROW_FILTER_FORBIDDEN
403
The credential cannot use the requested escrow filter.
ESCROW_MILESTONE_TARGET_OUT_OF_RANGE
422
A milestone target does not fit in a u32.
ESCROW_RECEIVER_MEMO_OUT_OF_RANGE
422
receiverMemo does not fit in a u32.
INVALID_CURSOR
422
Malformed pagination cursor.
PLATFORM_FEE_TOO_HIGH
422
platformFee plus the Trustless Work fee would exceed 100%.
Trustlines & assets
ESCROW_RECEIVER_TRUSTLINE_MISSING
422
A role that receives escrow funds has no trustline for the escrow token.
STELLAR_TRUSTLINE_INVALID_FORMAT
422
trustline could not be resolved to an asset contract.
STELLAR_TRUSTLINE_MISSING
422
Escrow state carries no readable trustline address.
STELLAR_TRUSTLINE_NOT_FOUND
422
No contract deployed at the trustline address on this network.
STELLAR_TRUSTLINE_NOT_SEP41
422
The contract does not implement the SEP-41 token interface.
STELLAR_UNSUPPORTED_DECIMALS
500
The token reports decimals outside the supported range.
TRUSTLINE_DECIMALS_UNSUPPORTED
422
The asset decimals are outside the supported [0, 18] range.
Stellar network errors
Transaction submission
Raised by POST /stellar/send-transaction: either the envelope is rejected before broadcast (not built by this API, wrong shape) or the network refuses it.
STELLAR_INVALID_SIGNED_XDR
422
signedXdr is not a valid transaction envelope.
STELLAR_TX_BAD_AUTH
422
The signature does not match the source account.
STELLAR_TX_BAD_AUTH_EXTRA
422
The transaction includes signatures that no operation needs.
STELLAR_TX_BAD_SEQ
409
Stale sequence number; rebuild and resubmit.
STELLAR_TX_CONTRACT_NOT_ALLOWED
422
Transaction invokes a contract this API does not manage.
STELLAR_TX_FEE_BUMP_INNER_FAILED
422
The inner transaction of the fee bump failed.
STELLAR_TX_FEE_BUMP_REJECTED
422
Fee-bump transactions are not accepted.
STELLAR_TX_HOST_FN_NOT_ALLOWED
422
Only invokeContract host functions may be submitted.
STELLAR_TX_INSUFFICIENT_BALANCE
422
The source account cannot cover the fee.
STELLAR_TX_INSUFFICIENT_FEE
422
The fee is below what the network currently demands.
STELLAR_TX_INTERNAL_ERROR
503
The network reported a transient internal error.
STELLAR_TX_MISSING_OPERATION
422
The transaction does not contain any operations.
STELLAR_TX_NOT_SUPPORTED
422
Transaction type not supported on the current protocol.
STELLAR_TX_NO_OPS
422
Transaction carries no operations.
STELLAR_TX_NO_SOURCE_ACCOUNT
422
The source account does not exist on the network.
STELLAR_TX_OPERATION_FAILED
422
One or more operations failed.
STELLAR_TX_OP_NOT_ALLOWED
422
Only Soroban invokeHostFunction operations may be submitted.
STELLAR_TX_TOO_EARLY
422
Submitted before the transaction validity window.
STELLAR_TX_TOO_LATE
422
The transaction validity window has passed.
STELLAR_TX_UNPARSEABLE
422
signedXdr is not a valid transaction envelope.
Stellar infrastructure & state
RPC/Horizon connectivity, simulation plumbing, and archived contract state. Mostly retryable; report persistent ones with the traceId.
STELLAR_FACTORY_RETURN_SHAPE
500
The factory returned an unexpected value shape.
STELLAR_HORIZON_UNMAPPED
500
Horizon answered with an unrecognized error shape.
STELLAR_HORIZON_UNREACHABLE
500
Could not communicate with Horizon.
STELLAR_RESTORE_UNBUILDABLE
500
A state-restore transaction could not be built.
STELLAR_RETURN_VALUE_SHAPE
500
A contract returned data in an unexpected shape.
STELLAR_RPC_TIMEOUT
500
The Soroban RPC did not answer within the deadline.
STELLAR_RPC_UNAVAILABLE
500
The Soroban RPC is unreachable.
STELLAR_SIMULATION_FAILED
500
Contract simulation failed.
STELLAR_SIMULATION_MISSING
500
The RPC returned no simulation result.
STELLAR_STATE_ARCHIVED
409
Contract state is archived; sign the provided restoreXdr and retry.
STELLAR_TX_FAILED
500
The network rejected the transaction.
STELLAR_UNKNOWN_CONTRACT_METHOD
500
The target contract does not expose the invoked method.
Transport-level errors
Generic codes produced by the HTTP layer when no domain-specific code applies.
BAD_REQUEST
400
The request failed basic validation.
CONFLICT
409
The request conflicts with current state.
FORBIDDEN
403
The credential lacks permission.
HTTP_ERROR
500
A non-standard HTTP error status was produced.
INTERNAL_ERROR
500
An unexpected server error occurred.
NOT_FOUND
404
No route or resource matches the URL.
SERVICE_UNAVAILABLE
503
A dependency is temporarily unavailable.
TOO_MANY_REQUESTS
429
You exceeded the rate limit.
UNAUTHORIZED
401
Authentication is required or failed.
VALIDATION_ERROR
422
The request body failed validation.