How errors reach your code
The server attaches a code to every Permissions error, but not every client receives it. The REST API and the REST SDK always return the code. The JavaScript SDKs receive only a few codes, listed in the Warning below, and get most Permissions errors as plain text without one. Find your client here, then look up the code in the sections below.The JavaScript SDKs export no class for API errors. SDK calls reject with an error object that carries
code and status, plus data when the server returned JSON. The object is not always an Error instance, so check its code property rather than its class. Signing calls are the exception in the web and React SDKs: when the server refuses one, for example with a policy denial, they currently reject with a generic error that has no code. The server SDK and the React Native SDK keep the code, status and data.Signing
These errors come from the REST signing endpoints (sign-raw, sign-transaction, sign-message, sign-typed-data, sign-authorization and transfer) and from SDK signing calls. Para evaluates your policies before it signs, so a policy error means nothing was signed.
Review required
When the deciding rule requires approval, a REST signing call returns403 with POLICY_REVIEW_REQUIRED and does not sign. In the server SDK and the React Native SDK, signing with an app-owned wallet throws the same error, with the fields in error.data.
The web and React SDKs currently reject with a generic error that has no data.
SDK signing with a user’s wallet works differently: the server returns a pending transaction, and the SDK sends the user to review and waits, or returns the review URL in handoff mode. Those outcomes are listed under SDK error classes.
An approval case is tied to its request: the
Idempotency-Key, or the request body when you send no key. Once the case can no longer sign that request, every resend returns POLICY_REVIEW_REQUIRED with the same case. That happens when the case is expired, invalidated or cancelled, and when it is completed but was already used to sign or passed its seven-day lifetime. A rejected case returns POLICY_DENIED with review-rejected until its lifetime ends. To start over, resend with a new Idempotency-Key. Case statuses are described in Approval requirements.Approval cases
These errors come from reading, deciding and cancelling approval cases, for example withgetAccessibleApprovalCase, approveApprovalCase, rejectApprovalCase and cancelApprovalCase in the SDKs, or GET /v1/permissions-v2/approval-cases and POST /v1/permissions-v2/approval-cases/{caseId}/cancel on REST. For case statuses and the reasons a case ends, see Approval requirements.
A user named as
initiatorUserId can cancel the case with cancelApprovalCase, but cannot read it from the SDK. getAccessibleApprovalCase refuses with INITIATOR_CANNOT_REVIEW, getInitiatedApprovalCase refuses with user did not initiate this approval case, and neither list includes the case. Your backend reads the case with GET /v1/permissions-v2/approval-cases/{caseId} and gives the user its caseId.Decision refusals
A refused approve or reject returns403 with the message approval decision is not allowed and one of these codes.
Approval signatures
These errors apply when an approval requirement collects transaction signatures (evidence: "transaction_signature"), for example with createApprovalSignatureCollection, signApprovalTransaction and getApprovalSignatures. Each signature must come from the user’s own wallet of the collection’s wallet type. createApprovalSignatureCollection opens an approval case, so it can also return the case-opening errors under Review required.
Approval administration
These errors come from managing who can approve: approver assignments, wallet authorization scope bindings and approval configuration. Your backend reaches them on/v1/permissions-v2 REST routes, and configuration managers reach them through updateApprovalConfiguration and resetApprovalConfiguration in the SDKs. Every write takes an expectedRevision and an optional force.
Policy authoring
These errors come from creating, replacing, activating, deactivating and archiving policies withpara keys permissions and in the Developer Portal. The Developer Portal shows each error’s message and path next to the JSON. The CLI reports them as described under CLI.
Validation without saving, such as
para keys permissions validate, returns 200 with { "valid": false, "errors": [...] } instead of an error. Requesting a production review returns 409 with { "status": "ineligible" } when no Development key has an active policy or the Production key is not awaiting review, and 503 with { "status": "delivery-failed" } when the request could not be delivered.User parameters
These errors come from reading and saving a user’s adjustable limits:listUserAdjustablePolicies, getUserPolicyParameters, listUserPolicyParameterHistory, updateUserPolicyParameters and resetUserPolicyParameters in the SDKs, and the GET /v1/permissions-v2/users/{userId}/user-parameters routes on REST. SDK calls receive them as plain text.
Saved values belong to one version of a policy. After you publish a new version, each user who saved their own values must confirm them.
getUserPolicyParameters returns status: "needs_confirmation" with the earlier values in previousValues, and signing under that policy is denied with parameter_configuration_invalid until the user saves or resets their values. Users who never saved values get the new defaults.Policy reads, usage and consent
These errors come from reading policies, a user’s spending against a policy and a user’s consent. In the SDKs, that islistPolicies, getPolicy, listApplicablePolicies, getApplicablePolicy, getUserPolicyUsage, listUserPolicyConsents and getUserPolicyConsent. On REST, it is the /v1/permissions-v2/policies, /v1/permissions-v2/users/{userId}/policies/{policyId}/usage, /v1/permissions-v2/wallets/{walletId}/policies/{policyId}/usage and /v1/permissions-v2/users/{userId}/delegation-consents routes. SDK calls receive them as plain text. When Permissions is not enabled for your app, the list reads return empty lists.
Pending transaction review
When arequire_approval rule has no approval requirement, POLICY_REVIEW_REQUIRED carries a reviewId. Your backend can approve or reject reviews from REST or standard app-owned SDK signing with your app’s server secret through POST /v1/permissions-v2/reviews/{reviewId}/approve or /reject. Both return 200 with the review’s current status, even when the review has already ended as expired, rejected or consumed.
After approved, retry identical SDK signing input without resumeApprovalCaseId only while the approval is unused and unexpired and the request and policy binding still match. Para re-evaluates the request, so approval status alone does not guarantee a signature. The Para Portal handles a user’s own pending transactions.
Idempotency
REST signing identifies a request by itsIdempotency-Key, or by the request body when you send no key. Para also uses that identity to tie the request to its approval case. Spend reservations use the Idempotency-Key only.
SDK error classes
The SDKs raise these classes in addition to the server codes above. The review classes come from the JavaScript SDKs when a signing call needs review. The REST SDK also throwsParaRestValidationError before it sends a request, with the message <name> is required, when a required ID or body is empty.
CLI
The CLI receives every error as JSON but prints its own message and exit code. Run with--json to read errorCode, exitCode and details.
create and replace validate the policy before they write it, and report an invalid policy the same way as para keys permissions validate. The CLI prints each error, or { "valid": false, "errors": [...] } with --json, and exits with 10 without an errorCode. details.errors appears with API_VALIDATION_ERROR only when the write or lifecycle call itself is rejected, for example when activate finds that conditional approvals or adjustable parameters are not enabled for your app (permissions_v2_extension_unavailable). For other API errors, including any 403, the CLI prints its own guidance in place of the server message.
Before it calls the API, the CLI can also exit with
AUTH_ERROR when you are not logged in (exit 3) or your session has expired (exit 4), and with CONFIG_NO_ORG_AND_PROJECT (exit 9) when no organization and project are selected.
Denial reasons
deniedBy[0].reason explains a POLICY_DENIED response. policyId and ruleId name the deciding rule and are omitted when no rule won. A rule with effect: "require_approval" reports its rule the same way in the reason of POLICY_REVIEW_REQUIRED. So does an allow rule that Para holds for the wallet owner’s review, and Para’s baseline review of a user-owned wallet, which reports matched:para:review-user-owned.
When a rule needs a fact that Para cannot read for a request, the rule’s outcome is unknown. Para denies the request with the fact reason when that rule’s effect outranks the rule that would otherwise decide, or when no other rule matched. It does not fall back to Para’s baseline policies in that case.
Policy validation codes
Policy writes and validation return these codes inerrors[].code, each with a path such as $.rules[0].when and a message. A value that does not match the policy schema returns partner_policy_schema_invalid, and a key the schema does not define returns policy_schema_field_unknown. The other codes report problems that the schema alone does not catch. Read path and message together. For the policy format itself, see Policy JSON schema and Facts and conditions.
Leave
layer out of policies you write for the CLI or the Developer Portal. Para sets it. A layer other than "partner" fails validation at $.layer: "para" returns policy_layer_owner_mismatch, and any other value returns layer_invalid.Schema
Schema codes identify unrecognized fields, malformed documents or a missing policy mode.Selector
Selector codes identify invalid wallet, user, network or app targeting.Rules
Check these codes for repeated rule IDs, unsupported actions and effects that the ownership model does not allow.Conditions and facts
These codes cover fact availability, operator and value compatibility, condition structure and metering declarations.Parameters
Parameter codes cover IDs, default values and where adjustable values can be declared.Approval requirements
These codes report repeated requirement IDs or features that are not enabled for the app.
A
minimum_amount setting in safeKnobs can declare a min and max range. If min is above max, or the stage’s minimumAmount falls outside the range, validation returns partner_policy_schema_invalid at $.rules[i].approvalRequirement.safeKnobs[j] with the message minimum configurable amount threshold must not exceed maximum or the published amount threshold must be within the configurable range.
Policy records
These codes come from saving and changing policy records. The conflict codes return409. The others return 400.