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
Use the error code to distinguish a signature recovery mismatch from other 422 validation failures. 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.
After correcting the integration, obtain fresh authorization for the same pending resource and sign exactly its 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 |
Signing authority expired. Read client.payments.recovery(paymentId) through the
authenticated BFF. If can_continue is true, begin a fresh member action for the same
payment ID and complete its registered authorization ceremony. Do not create another payment to
resume this one. If cancellation is available, require an explicit choice before cancelling. |
Payment stuck in pending_sign |
The member has not signed yet. Recover the existing payment from activity and obtain fresh authorization through the BFF. A signing URL is a locator, not bearer or member-session authority. |
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
XKOVA-Webhook-Event-Id(the envelopeid) so a repeated event is a no-op. UseXKOVA-Webhook-Delivery-Idfor delivery-level tracing.
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.

