Troubleshooting
Every refusal in Pehmen names itself. Find the words you are seeing.
On sign-in and account
| You see | Meaning | Do |
|---|---|---|
| The sign-in page asks for Authenticator code | Two-factor is on for your account | Enter the six digits. A code works once per 30 seconds. |
| That code was not accepted | Wrong code, or the same code used twice in one step | Wait for the next code. |
| Your email address is not verified yet on the overview | The verification link was never clicked | Press Send the verification link again. Only accepting invitations is blocked. |
| Could not accept the invitation | Wrong account, unverified email, or expired invitation | Sign in with the invited address, verify it, or ask for a new invitation. |
On buttons
| You see | Meaning | Do |
|---|---|---|
| Confirm it is you with a code field | The action needs a second factor verified in the last five minutes | Enter the code. The action retries under a new idempotency key. |
This step needs the … permission, which your roles do not include | Your role lacks it | Ask an owner to change your role, or ask someone with it. |
| You requested this …, so you cannot also grant it | Dual control | Someone else approves. |
| waiting for a second approver | The action opened an approval instead of completing | Give the approval id to a second person with the approve permission. |
| A button is greyed but still focusable | Not yet available; the sentence under it says why | Do the thing it names (validate first, wait out cooling-off, …). |
approval_stale | The content changed between approval and execution | Approve again. |
ato_session_blocked | You or the approver changed credentials in the last 24 hours | Wait, or have someone else act. |
On connections
| You see | Meaning | Do |
|---|---|---|
LIVE_KEY_IN_TEST_ENVIRONMENT | A live key | Create the key in the provider's test or sandbox mode. |
SECRET_KEY_NOT_ALLOWED_USE_RESTRICTED | sk_test_ | Stripe: Create restricted key with Write on PaymentIntents, Charges, Refunds, Webhook Endpoints. |
PROVIDER_AUTH_FAILED | The provider rejected the key | Check it was copied whole and belongs to the sandbox account. |
PROVIDER_SCOPE_INSUFFICIENT | Missing permissions | Add the four Stripe permissions above. |
DEGRADED with WEBHOOK_REGISTRATION_SCOPE_MISSING | Stripe key lacks Webhook Endpoints: Write | It still routes. Recreate the key with the permission and re-validate, or create the endpoint in Stripe and paste the whsec_ secret. |
| This connection still needs a webhook signing secret | HitPay or Airwallex | Create the endpoint in the provider dashboard at the URL shown; paste the secret through the API. |
On payments
| You see | Meaning | Do |
|---|---|---|
no_eligible_route / NO_ELIGIBLE_ROUTE | No connection survived the filters | Read the matrix on the payment page. Common: no PAYIN connection, PayNow with Manual capture, a revoked connection. |
intent_state_invalid on confirm | An attempt is already in flight, or the intent is terminal | Wait for the outcome, or create a new intent. |
Stays PROCESSING | The worker is dispatching; the outcome comes by webhook or query | Wait. On a real sandbox it is seconds. Check the inbox under Webhooks for the provider's event. |
OUTCOME_UNKNOWN | The provider did not answer clearly | Nothing. The query loop runs for up to about three hours; then it is MANUAL_REVIEW. |
MANUAL_REVIEW on an attempt | Contradictory observations or query budget exhausted | No self-service action exists in this release. Raise it with the platform team. |
DENIED | The Gate said no | Read the Gate decision's reason codes; adjust the policy if they are wrong. |
On policies
| You see | Meaning | Do |
|---|---|---|
| The rules engine refused this definition | Schema or DSL error, with paths | Fix the named path. Unknown feature, reason code, decision or operator are the usual causes. |
UNREACHABLE_RULE | A condition can never be true, or an earlier rule always matches first | Fix or remove the rule. |
| Submit refused: replay | No replay for this exact definition | Run Replay this window, then submit. |
POLICY_LOCK_CONFLICT | Someone else changed the version meanwhile | Reload and retry. |
On trust and payouts
| You see | Meaning | Do |
|---|---|---|
| seller has no verified notification channel | Nobody trustworthy to notify | Add and verify a channel for the seller first. |
cooling_off_active | The window has not elapsed, or a notice is undelivered | Wait; check the notification rows on the change page. |
HELD with FULFILLMENT_EVIDENCE_TIER_TOO_LOW | No tier-2 evidence for the orders in the release condition | Send a signed fulfillment event, then approve. |
| Release refused on a demo connection | Pooled demo credentials cannot dispatch | Use your own Airwallex sandbox connection. |
FAILED_AFTER_PAID | The provider reported paid, then failed | Work the PAID_THEN_FAILED exception and the case it opened. |
On webhooks
| You see | Meaning | Do |
|---|---|---|
webhook_url_rejected | Not HTTPS on 443, or a private or loopback address | Use a public HTTPS URL. |
Deliveries FAILED with your status | Your server answered non-2xx, timed out (10 s), or redirected | Fix the endpoint; retries continue for 20 attempts. |
Endpoint DISABLED | Attempts exhausted | Fix the endpoint, Enable delivery, then Replay the deliveries. |
| Inbox shows signature invalid | The provider's event did not verify against the stored secret | Check the secret pasted for the connection; rotate it at the provider and paste again. |
On the API
| Status and code | Meaning |
|---|---|
400 idempotency_key_required | Add an idempotency-key header. |
409 idempotency_conflict | Same key, different body. Use a new key. |
409 idempotency_in_progress | The same request is still running. Wait and read the resource. |
403 environment_mismatch | A test key naming live, or the reverse. |
403 forbidden with "API keys cannot step up" | Needs a person with a fresh second factor; keys cannot step up. |
404 not_found | Also what you get for another workspace's object. |
429 rate_limited | Honour retry-after. |
If none of these fit, quote the request id shown under the error; every response carries one in the request-id header too.