FAQ and Troubleshooting
The failures integrators hit most often, and what to do about each. Always start from the response code, not the HTTP status alone, and keep the correlation_id from the response. That id is the fastest path to a root cause.
Always start from the code
Every error response carries a stable code and a correlation_id. Branch your
handling on the code, and log the correlation id. See Errors and Correlation IDs
for the full envelope and the catalog of live codes.
Authentication and scope
| Symptom | What it means and how to fix it |
|---|---|
401 unauthorized |
No valid credential. Check the Authorization: Bearer xkv_... header is present and
that the key has not been revoked. See Authentication. |
401 active_scope_unavailable |
An XKOVA management Console session pointed at a scope it cannot act in, usually a stale cached pointer. Clear the active scope header and re-pick a scope you are authorized for. |
403 on a mutation you expected to work |
Your role lacks the required permission. Check the permission the operation needs against Roles and Permissions. |
Member Authentication
The confidential member-session exchange returns member-auth-specific errors. See Member Browser and BFF Integration for the flow and Errors and Correlation IDs for the full catalog.
| Symptom | What it means and how to fix it |
|---|---|
401 member_auth_token_invalid |
The provider proof, XKOVA refresh credential, or session reference is invalid or was already consumed. Restart provider authorization for a proof failure. For refresh replay, discard the local session family and require fresh authentication. |
401 member_auth_session_revoked |
The XKOVA session is revoked, expired, or no longer matches current application or member policy. Delete the first-party application session and begin a new authentication flow. |
401 member_auth_refresh_replay_detected |
A single-use refresh credential was reused or two refreshes raced. XKOVA revoked the family. The BFF store must serialize refresh for one application-session reference across all instances. |
Payments and signing
A 422 on submitting signatures is a signature recovery mismatch. The signed bytes did not
recover to the wallet the server expected. The most common causes are:
- The wallet identity used to derive the address did not match the one the signing session expects.
- A numeric (
uint256) field was not restored to a big integer before signing, so it signed as a different value. - The wrong field name was signed. The transfer intent uses
recipient, notto, and the field set differs across intent types.
The fix is the same in every case: re-fetch the signing session and sign exactly the returned
typed_data, restoring big integers for every numeric field. See
Non-custodial Model for how signing and submission fit together.
| Symptom | What it means and how to fix it |
|---|---|
401 fetching a signing session |
The capability token in the signing link expired. Re-fetching the session returns the same token, which is still expired, so the only fix is to create a new payment. That stamps a fresh expiry and mints a fresh signing token. Sign promptly. |
Payment stuck in pending_sign |
The member has not signed yet. The signing link is on the payment; the token within it authorizes the session. |
Payment failed with failure_reason_code: on_chain_revert |
The transaction landed on chain but the contract reverted. There is no reverted status;
the payment moves to status: failed with failure_reason_code: on_chain_revert,
so branch on failed plus the failure reason code. This is terminal. Note that inclusion in
a block is not success; confirmation checks the on chain status, not just that the transaction was
mined. See Transfers and Settlement. |
Idempotency and retries
409idempotency conflict. You reused anIdempotency-Keywith a different body. Use a fresh key for a new logical write, and reuse the same key only to retry the identical request. See Idempotency.- When to retry. Branch on the error's
code, not the bare HTTP status: the error catalog documents each code's retry strategy. A transient upstream502or503is generally safe to retry with backoff (a rate-limited response carries aRetry-Afterheader); a403or422is not, retrying will not change the outcome. See Rate Limits for backoff guidance.
Treasury
409executing a transfer. The signer quorum is not yet met. Collect more signer attestations until the N of M threshold is reached, then execute. See Treasury.- Self-approval rejected. The request creator cannot approve their own transfer when the approval clause can be satisfied without them. A different signer must attest. See Policies and Quorum Governance.
Webhooks
- Signature verification fails. Verify against the webhook signature headers over the raw request body. Do not re-serialize the JSON before verifying, or the bytes will not match. See Webhooks.
- Duplicate deliveries. Retries can re-deliver an event. Handle events idempotently using the delivery id header so a duplicate is a no-op.
Still stuck
Capture the correlation_id from the response and the timestamp of your request. Those two
values are the fastest path to a root cause. See Support for where to take
them.