When a Ripple Custody (Wallet) API request fails, the response has an HTTP error status and a JSON body that describes the error. This page explains the body, how its code maps to the HTTP status, how to read the PAL reason codes, and how to fix common errors. For general API conventions, including authentication and retries, see API conventions.
Error response format
Field
Description
code
The gRPC status code for the error, as a number. The HTTP status of the response is derived from it. See Status codes.
message
A human-readable description of the error. Don't parse it; it can change.
details
An array of objects, each identified by @type. The API returns at most two kinds of entry. A 401 response has no details.
The details array can contain:
ErrorInfo (type.googleapis.com/google.rpc.ErrorInfo): reason is a PAL reason code that identifies the specific problem. domain is the API host that produced the error, such as api.sandbox.palisade.co. metadata is an object that is usually empty. Request validation errors include an ErrorInfo entry with reason PAL000.020 and the generic message invalid request, which doesn't name the field. Some errors have no ErrorInfo entry: a body or query parameter that the API can't parse (the message is the parser error), and a method that the path doesn't support.
RequestInfo (type.googleapis.com/google.rpc.RequestInfo): requestId identifies the request. Every error response includes it except a 401, whose body is only {"code": 16, "message": "Unauthorized"}.
Example
This response comes from a request whose credential doesn't have permission for the operation:
The code field uses gRPC status codes. Ripple Custody (Wallet) maps them to HTTP statuses as follows:
code
gRPC status
HTTP status
Typical cause
3
INVALID_ARGUMENT
400
A field is missing, malformed, or out of range. Fix the request before you retry.
9
FAILED_PRECONDITION
400
The resource isn't in a state that allows the action, for example deleting a policy rule that's still pending approval.
16
UNAUTHENTICATED
401
The access token is missing, invalid, or expired. Request a new token and retry.
7
PERMISSION_DENIED
403
The credential's type or permissions don't cover the operation or the resource.
5
NOT_FOUND
404
The resource doesn't exist, or your credential can't see it.
6
ALREADY_EXISTS
409
An equivalent resource already exists, for example a webhook with the same name or a second limit of the same type on a wallet.
12
UNIMPLEMENTED
501
The path doesn't support the HTTP method, for example PUT or PATCH on a webhook. The message is Method Not Allowed.
13
INTERNAL
500
An unexpected server error. Contact support with the requestId if it persists.
14
UNAVAILABLE
503
The service is temporarily unavailable.
Reason codes
A reason code has the form PAL<service>.<problem>. The three-digit service number identifies the area of the platform that rejected the request, and the problem number identifies the specific error within it. Reason codes are stable, so use them, not message, when your code handles specific errors.
Service
Area
PAL000
Common errors shared by all services, such as authentication and permissions
PAL001
Devices
PAL002
MPC quorums and wallet keys
PAL003
Approvals
PAL004
API credentials
PAL005
HSM keystore
PAL006
Policies
PAL007
Connections
PAL008
Balances
PAL009
Vaults and wallets
PAL010
Transactions
PAL011
Organizations and users
PAL012
Identity
PAL013
Address book
PAL014
Compliance
PAL015
Webhooks
PAL016
Backups
PAL017
Workflows, including asset sweeping
PAL018
Audit logging
PAL019
Blockchain connections
PAL020
Registry
Common errors
These reason codes can come from any endpoint:
Reason
Message
What to do
PAL000.001
unauthenticated request
Send a valid access token in the Authorization header. A missing, malformed, or expired token returns 401 with no reason code.
PAL000.002
unauthorized request
Check that the credential's type and permissions cover the operation and the vault or wallet you're accessing. See Manage API credentials.
PAL000.003
invalid permission
The credential's permissions are malformed. Recreate the credential.
Check that the address is valid for the wallet's blockchain.
PAL000.013
invalid asset ID
Check the asset ID format.
PAL000.014
invalid signature
Check the signed payload and signature.
PAL000.015
invalid token
Request a new access token.
PAL000.020
invalid request
The request failed validation: a required field is missing or empty, a value is out of range or not in an allowed format, or an enum value isn't recognized. Also returned by the token exchange for a wrong clientId or clientSecret. Check the request against the API reference.
Errors documented with their features
Pages that document a feature also list the reason codes it returns:
Failed transactions: transactions carry a problems array with reason codes and retryability. See Transaction problems.
Troubleshoot common errors
These tables list errors that the API returns in practice, grouped by area, with their likely cause and fix. Some requests succeed when you might expect an error, so the tables also include a few 200 responses that usually mean something went wrong. For more behaviors to plan for, see Behaviors to know.
Authentication
You see
Reason
Cause
What to do
400invalid request from POST /v2/credentials/oauth/token
PAL000.020
The clientId or clientSecret is wrong, or the body is missing. The token exchange doesn't return 401.
Check that you send the credential's clientId and clientSecret in a JSON body. See Get and use an access token.
401Unauthorized, with no details
None
The Authorization header is missing, or the token is malformed or expired.
Request a new token and send it as Authorization: Bearer <accessToken>.
403unauthorized request
PAL000.002
The credential's type doesn't cover the endpoint, for example a MONITORING credential calling GET /v2/vaults.
Use a credential of the type that covers the endpoint. See Credential types.
Permissions
You see
Reason
Cause
What to do
403 on the policy rules endpoints (/policy-rules), while the wallet limit endpoints work
PAL000.002
The CONTROLS credential doesn't have the policy:* permissions. The wallet limit endpoints use the separate keylimit:* permissions.
A required field is missing or empty, a value is out of range or in the wrong format, or an ID in the path isn't a UUID. The message doesn't name the field.
The page size is above the maximum (1,000, or 100 for the top-level pageSize on some operations), pagination.orderBy isn't a snake_case sortable field (for example createdAt instead of created_at), or a filter value isn't recognized.
400 with a parser message, such as invalid path: "domain" is not a message or invalid value for string field search, and no ErrorInfo
None
A filter has an operator it doesn't take, a filter that needs an operator has none, or a body field has the wrong type, for example an object where the API expects an array or a string.
200 on deleting a webhook or subscription that doesn't exist
None
Deletes return 200 whether or not the object existed.
Don't treat a 200 as proof that the object existed.
Sweeps
You see
Reason
Cause
What to do
400sweep configuration already running
PAL017.006
A sweep for this configuration is already running.
Wait for the current run to finish, then trigger the sweep again. See Trigger a sweep.
400invalid request on a sweep trigger
PAL000.020
The configuration ID isn't a UUID.
Check the configuration ID.
403 on a sweep trigger
PAL000.002
The request doesn't use a TRANSACTIONS credential.
Use a TRANSACTIONS credential.
200 with no transactions for a sweep instance
None
No sweep instance has this ID.
Check the sweep instance ID in the console's sweep run history.
Get help with an error
Log the requestId from every error response. If you can't resolve an error, contact Ripple Support with the requestId, the reason code, and the time of the request.