# Troubleshooting

Use the status, error message or capture reason to find the relevant correction below. RP means relying party; OIDC, OpenID Connect; SSC, Secure Signature Confirmation; LOA, level of assurance; and PAdES, PDF Advanced Electronic Signature.

## Registration and credentials

| Message or symptom | Why you see it | Fix |
|---|---|---|
| `Unknown RP client_id` | Wrong client ID, or the registration was reset | Copy the client ID from the [RP dashboard](https://cloud.securysign.com/#/rp/dashboard) |
| `RP registration not approved. Status: pending` | SecurySign has not approved your registration yet | Wait for approval |
| `Invalid client credentials` on `/ssc/token` | Wrong SSC secret | Use the SSC secret, not the OIDC client secret |
| `invalid_client` on `/kyc/*` | Wrong OIDC client ID or secret in Basic auth | Check both. Rotating the secret invalidates the old one. |
| `403 CSRF token validation failed` on `/kyc/*` | The request carried no `Authorization` header | Check that your client ID and secret environment variables are set |
| `This relying party is not enabled for Identity Verification` | Your RP lacks the `signa-kyc` scope | Request the scope from the RP dashboard |
| `invalid_scope` at login | A requested scope is not assigned to your client | Request only assigned scopes |
| `Not authorized for this RP` on `/rp/*` | You signed in with an account other than the RP's `contact_email` | Sign in with the contact email |

## Signing

| Message or symptom | Why you see it | Fix |
|---|---|---|
| `RP origin not authorized: …` | The origin is not an approved signing origin | [Authorise it](#/docs/rp-integration-guide#3-authorise-additional-signing-origins) |
| Blank iframe | The `#` is missing from the URL, or the token expired | Use `/#/sign-frame`; tokens are valid for 5 minutes |
| No passkey prompt | Missing `allow="publickey-credentials-get *"`, an HTTP page, or no passkey yet | Add the attribute, serve over HTTPS, or [enrol](#/docs/enrolment) the user |
| `Requested LOA LOA-4 exceeds RP maximum LOA-2` | LOA-4 is not enabled | [Enable LOA-4](#/docs/rp-integration-guide#5-enable-loa-4) |
| `LOA-4 requires an email hint` | LOA-4 token request without `email` | Add `email` to the request |
| `User not found for email: …` | No SecurySign account for that address | Send the signer through [enrolment](#/docs/enrolment) |
| `No credential found for user` | The signer has no passkey | Send the signer through [enrolment](#/docs/enrolment) |
| `Missing Authorization header` or `Invalid or expired token` on `/v2/*` | No token, or not a current signed-in user's token | See [Core concepts](#/docs/core-concepts#credentials) |
| `Token missing subject claim` | Your client's access tokens carry no `sub` | Contact support to add the `basic` scope to your client |
| `Origin mismatch — possible phishing attack` | The passkey prompt ran outside a SecurySign origin | Have your user approve in the [signing frame](#/docs/api-hash-signing#2-show-the-request-to-your-user) |
| `Passkey signature verification failed` | The approval was not made by the user's registered passkey | Approve with the passkey the user enrolled |
| `Challenge mismatch — dynamic linking failed` | The passkey signed a different challenge | Sign the challenge, or hash, returned for this request |
| `Daily signing limit exceeded (…)` | The day's signing allowance is used up | Wait for 00:00 UTC or [change plan](#/docs/limits) |
| `410` `This signing operation expired. …` | PAdES finalize came more than 5 minutes after prepare | Prepare again |

## Identity verification

| Message or symptom | Why you see it | Fix |
|---|---|---|
| CORS error on `/api/kyc/faceapi/…` | The browser is calling SecurySign directly | Serve the [pass-through](#/docs/sdk-reference#add-the-pass-through) |
| `422` `x-client-key Field required` | The pass-through dropped the header | Forward `x-client-key` |
| `401` `Invalid or expired liveness session` | The token expired or was replaced | Open one new session per attempt |
| `409` from `/face` | The ID was not submitted, or the last submission failed | Submit the ID again |
| Repeated `document_not_authentic` | Glare, blur, cropping or a laptop camera | Retake the photo, or use the [phone handoff](#/docs/kyc#6-optional-continue-on-a-phone) |
| `selfie` is `null` with `return_selfie` | Capture is unfinished, the verdict is unsuccessful, or the retained image is unavailable. | Read `status` and `reasons` for the verification outcome; [the selfie rules](#/docs/kyc#when-you-get-the-selfie) explain image availability. |
| `403` from `POST /kyc/customers/selfie` | The verification is not `verified` | Get the selfie once the verdict is `verified` |
| Face capture ends with `stopped` and `BAD_FACE_QUALITY` | The face was too dark, blurred or small, often from a window behind the customer | Ask your customer to face a light source and hold the camera steady at eye level; see [every `stopped` reason](#/docs/sdk-reference#component-api) |

## Enrolment

| Message or symptom | Why you see it | Fix |
|---|---|---|
| `error=access_denied` with `kyc_customer_id must be a customer this client_id has verified…` | You have no `verified` verification of this customer with this `client_id`, or another person enrolled with it | Verify the customer first, or leave `request_uri` out; see [Reuse a verification you ran yourself](#/docs/enrolment#reuse-a-verification-you-ran-yourself) |
| `error=access_denied` with `request_uri is unknown or has expired…` or `request_uri was already used by another person…` | The link was opened more than 600 seconds after you requested it, by a second person, or with another `client_id` | Request a new `request_uri` and send a new link |
| `error=access_denied` with `Identity verification required before enrolment` | No verified identity for your customer when enrolment finished | Send your customer through the [enrolment link](#/docs/enrolment#enrol-through-securysign-directly) again |
| `invalid_grant` from `/enrolment/token` | The code expired after 120 seconds, was used, or the `code_verifier` or `redirect_uri` differs | Send your customer through enrolment again |

## Webhooks

| Symptom | Fix |
|---|---|
| Webhook signature mismatch | Compute the HMAC over the raw body with the secret you registered |
| A webhook delivery is missing | Your callback uses a publicly reachable HTTPS URL and answers `2xx`; your backend can confirm completion through the authenticated event stream. |
| `callbackUrl` deliveries have no signature header | Confirm them with an authenticated call; only subscription deliveries are signed. |

## Contact support

If the failure persists after the listed correction, send the endpoint, HTTP status, error message and timestamp to [support@tenda.world](mailto:support@tenda.world).
