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 operator 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 partner_scope_denied |
A partner-scope key hit a tenant-scoped resource. Use a key bound to the tenant instead. See Authorization and RBAC. |
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 embedded member sign-in surface (/v1/member-auth/*) returns its own error codes. Two you
will hit while building sign-up and sign-in are credential and password-policy failures. See
Embedded Member Sessions for the flow and
Errors and Correlation IDs for the full catalog.
| Symptom | What it means and how to fix it |
|---|---|
401 member_auth_invalid_credentials |
A sign-in (POST /v1/member-auth/sign-in) presented an email and password that XKOVA IDP
rejected. The credentials are wrong; prompt the member to try again or reset their password. Retrying
the same input will not change the outcome. |
422 member_auth_weak_password |
A password you set does not meet the password policy. This surfaces on sign-up, on password reset confirmation, and on a member password change. Ask for a stronger password and resubmit. Retrying the same input will not change the outcome. |
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.