XKOVA Docs

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

SymptomWhat 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.

SymptomWhat 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, not to, 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.

SymptomWhat 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

  • 409 idempotency conflict. You reused an Idempotency-Key with 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 upstream 502 or 503 is generally safe to retry with backoff (a rate-limited response carries a Retry-After header); a 403 or 422 is not, retrying will not change the outcome. See Rate Limits for backoff guidance.

Treasury

  • 409 executing 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.