> For the complete documentation index, see [llms.txt](https://docs.pepeunchained.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pepeunchained.com/reference/errors.md).

# Error Reference

Every error code the SDK, the MCP server and the paymaster client can return: what it means, why it happens, how to fix it, the HTTP status route handlers use and whether a retry can help. Each code has a stable anchor, so the `docsUrl` on a `PepuError` (`https://docs.pepeunchained.com/reference/errors#<CODE>`) lands on its entry. Paste an error into [`explainError`](/sdk/errors.md) or the MCP tool `pepu_explain_error` to get its entry directly.

## Prerequisites

* None. For the SDK functions that produce these errors, see [SDK Error Catalog](/sdk/errors.md).

## Index

| Code                                                                      | HTTP | Retryable | Meaning                                                 |
| ------------------------------------------------------------------------- | ---- | --------- | ------------------------------------------------------- |
| [`CONFIG_BAD_URL`](#CONFIG_BAD_URL)                                       | 500  | no        | Invalid endpoint URL                                    |
| [`CONFIG_MISSING_ENV`](#CONFIG_MISSING_ENV)                               | 500  | no        | Missing environment variable                            |
| [`CONFIG_ORIGIN_MISMATCH`](#CONFIG_ORIGIN_MISMATCH)                       | 500  | no        | Origin is not allowed by Privy                          |
| [`CONFIG_PRIVY_CREATE_ON_LOGIN`](#CONFIG_PRIVY_CREATE_ON_LOGIN)           | 500  | no        | Embedded wallet never appears after login               |
| [`CONFIG_PRIVY_DASHBOARD`](#CONFIG_PRIVY_DASHBOARD)                       | 500  | no        | Privy dashboard misconfiguration                        |
| [`CONFIG_SERVER_ONLY`](#CONFIG_SERVER_ONLY)                               | 500  | no        | Server-only module imported in the browser              |
| [`AUTH_INVALID_TOKEN`](#AUTH_INVALID_TOKEN)                               | 401  | no        | Invalid or missing Privy access token                   |
| [`WALLET_COINBASE_UNSUPPORTED_CHAIN`](#WALLET_COINBASE_UNSUPPORTED_CHAIN) | 400  | no        | Coinbase Smart Wallet does not support PEPU             |
| [`WALLET_INJECTED_ACTIVE`](#WALLET_INJECTED_ACTIVE)                       | 400  | no        | An injected browser wallet is the active account        |
| [`WALLET_NOT_PROVISIONED`](#WALLET_NOT_PROVISIONED)                       | 409  | yes       | User has no embedded wallet yet                         |
| [`PRIVY_CHAIN_REJECTED_97741`](#PRIVY_CHAIN_REJECTED_97741)               | 502  | no        | Privy rejects server-side eth\_sendTransaction on PEPU  |
| [`PRIVY_KEY_QUORUM_MISMATCH`](#PRIVY_KEY_QUORUM_MISMATCH)                 | 500  | no        | Privy authorization key does not match the wallet owner |
| [`POLICY_NAME_TOO_LONG`](#POLICY_NAME_TOO_LONG)                           | 400  | no        | Privy policy or rule name is too long                   |
| [`POLICY_UNSCOPED`](#POLICY_UNSCOPED)                                     | 400  | no        | Session policy is not scoped                            |
| [`SESSION_APPROVAL_MISMATCH`](#SESSION_APPROVAL_MISMATCH)                 | 409  | no        | Session approval does not match                         |
| [`SESSION_EXPIRED`](#SESSION_EXPIRED)                                     | 410  | no        | Session expired                                         |
| [`SESSION_NONE`](#SESSION_NONE)                                           | 409  | no        | No active session                                       |
| [`BUNDLER_AA_FAILED`](#BUNDLER_AA_FAILED)                                 | 502  | no        | EntryPoint rejected the UserOperation                   |
| [`BUNDLER_UNREACHABLE`](#BUNDLER_UNREACHABLE)                             | 502  | yes       | Bundler or paymaster is unreachable                     |
| [`PAYMASTER_API_ERROR`](#PAYMASTER_API_ERROR)                             | 502  | no        | Paymaster API request failed                            |
| [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | 429  | yes       | Sponsorship cap reached                                 |
| [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | 403  | no        | Paymaster denied the sponsorship                        |
| [`PAYMASTER_DESTINATION_NOT_ALLOWED`](#PAYMASTER_DESTINATION_NOT_ALLOWED) | 403  | no        | Paymaster refused the call destination                  |
| [`PAYMASTER_FREE_TIER_UNAVAILABLE`](#PAYMASTER_FREE_TIER_UNAVAILABLE)     | 429  | yes       | Free tier cannot sponsor this operation                 |
| [`PAYMASTER_IDENTITY_REQUIRED`](#PAYMASTER_IDENTITY_REQUIRED)             | 401  | no        | A verified Privy account is required                    |
| [`PAYMASTER_NO_BALANCE`](#PAYMASTER_NO_BALANCE)                           | 429  | yes       | Sponsorship project has no balance                      |
| [`PAYMASTER_ORIGIN_NOT_ALLOWED`](#PAYMASTER_ORIGIN_NOT_ALLOWED)           | 403  | no        | Paymaster refused the request origin                    |
| [`PAYMASTER_PROJECT_NOT_CLAIMED`](#PAYMASTER_PROJECT_NOT_CLAIMED)         | 409  | no        | Sponsorship project is not claimed on-chain             |
| [`PAYMASTER_PROJECT_OWNER_CHANGED`](#PAYMASTER_PROJECT_OWNER_CHANGED)     | 403  | no        | Project owner changed since the credentials were issued |
| [`PAYMASTER_PROJECT_PAUSED`](#PAYMASTER_PROJECT_PAUSED)                   | 403  | no        | Sponsorship project is paused                           |
| [`PAYMASTER_RATE_LIMITED`](#PAYMASTER_RATE_LIMITED)                       | 429  | yes       | Paymaster API rate limit                                |
| [`PAYMASTER_SESSION_REQUIRED`](#PAYMASTER_SESSION_REQUIRED)               | 401  | no        | Paymaster owner session missing or expired              |
| [`PAYMASTER_UNREACHABLE`](#PAYMASTER_UNREACHABLE)                         | 502  | yes       | Paymaster service is unreachable                        |
| [`MULTICALL3_CANONICAL_ADDRESS`](#MULTICALL3_CANONICAL_ADDRESS)           | 500  | no        | Canonical Multicall3 address used on PEPU               |
| [`TX_GAS_UNDERSHOOT`](#TX_GAS_UNDERSHOOT)                                 | 502  | yes       | Gas limit too low                                       |
| [`TX_NONCE_RACE`](#TX_NONCE_RACE)                                         | 409  | yes       | Nonce conflict                                          |
| [`TX_REVERTED`](#TX_REVERTED)                                             | 502  | no        | Transaction reverted                                    |
| [`UNKNOWN`](#UNKNOWN)                                                     | 500  | no        | Unknown error                                           |

## Configuration

### CONFIG\_BAD\_URL

**Invalid endpoint URL**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** A configured bundler, paymaster or RPC URL is not a valid http(s) URL.
* **Fix:** Use a full URL such as <https://bundler.example.com>.

### CONFIG\_MISSING\_ENV

**Missing environment variable**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** A required environment variable is not set.
* **Fix:** Set the listed variables (see .env.example) and restart the process.

### CONFIG\_ORIGIN\_MISMATCH

**Origin is not allowed by Privy**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** The page origin (scheme, host and port) is not in the Privy app's allowed origins. A different dev port is the usual cause.
* **Fix:** Add the exact origin, including the port, to Privy dashboard Allowed origins.

### CONFIG\_PRIVY\_CREATE\_ON\_LOGIN

**Embedded wallet never appears after login**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** The dashboard's automatic embedded wallet creation is off, so createOnLogin never resolves.
* **Fix:** Create the wallet server-side with the ensure-wallet route (createEnsureWalletRoute), or enable creation in the Privy dashboard.

### CONFIG\_PRIVY\_DASHBOARD

**Privy dashboard misconfiguration**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** A required Privy dashboard setting is missing.
* **Fix:** Run checkPrivyDashboardConfig() and follow its fix list.

### CONFIG\_SERVER\_ONLY

**Server-only module imported in the browser**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** A server entry point was bundled into client code.
* **Fix:** Import server entries only from route handlers, server actions and scripts.

## Auth and wallet

### AUTH\_INVALID\_TOKEN

**Invalid or missing Privy access token**

* **HTTP status:** 401
* **Retryable:** no
* **Cause:** The request carried no bearer token, or Privy could not verify it.
* **Fix:** Send Authorization: Bearer \<getAccessToken()> and verify the token server-side.

### WALLET\_COINBASE\_UNSUPPORTED\_CHAIN

**Coinbase Smart Wallet does not support PEPU**

* **HTTP status:** 400
* **Retryable:** no
* **Cause:** Coinbase Smart Wallet is a smart-contract wallet on chains it knows; PEPU (97741) is not one of them, and it floods the console with unsupported-chain errors.
* **Fix:** Pin Coinbase to eoaOnly via createPepuPrivyConfig() from @pepu-chain/sdk/privy.

### WALLET\_INJECTED\_ACTIVE

**An injected browser wallet is the active account**

* **HTTP status:** 400
* **Retryable:** no
* **Cause:** wagmi's active account is a browser extension rather than the Privy embedded wallet.
* **Fix:** Pin the embedded wallet with useActiveWalletPin() from @pepu-chain/sdk/privy/wagmi.

### WALLET\_NOT\_PROVISIONED

**User has no embedded wallet yet**

* **HTTP status:** 409
* **Retryable:** yes
* **Cause:** The user is signed in but no embedded Ethereum wallet exists.
* **Fix:** Call the ensure-wallet route (useEnsureWallet or WalletGate) before acting.

## Privy

### PRIVY\_CHAIN\_REJECTED\_97741

**Privy rejects server-side eth\_sendTransaction on PEPU**

* **HTTP status:** 502
* **Retryable:** no
* **Cause:** Privy's server-side send path does not know chain 97741 and rejects it. Signing works; sending does not.
* **Fix:** Sign with eth\_signTransaction on the server and broadcast the raw transaction yourself (signAndBroadcast from @pepu-chain/sdk/session).

### PRIVY\_KEY\_QUORUM\_MISMATCH

**Privy authorization key does not match the wallet owner**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** Privy returned 401 'No valid authorization keys or user signing keys available': the server's PRIVY\_AUTHORIZATION\_KEY is not a signer on the wallet, or the key quorum id differs from the one the user granted.
* **Fix:** Make sure PRIVY\_AUTHORIZATION\_KEY is the private half of the key whose quorum id is NEXT\_PUBLIC\_PRIVY\_KEY\_QUORUM\_ID, and that the user granted that quorum as a signer.

## Session keys and policies

### POLICY\_NAME\_TOO\_LONG

**Privy policy or rule name is too long**

* **HTTP status:** 400
* **Retryable:** no
* **Cause:** Privy rejects policy and rule names of 50 or more characters (the real limit is 49).
* **Fix:** Shorten the policy or rule name to 49 characters or fewer.

### POLICY\_UNSCOPED

**Session policy is not scoped**

* **HTTP status:** 400
* **Retryable:** no
* **Cause:** A session policy needs a target contract, at least one function and an expiry.
* **Fix:** Pass contractAddress, functions and expiresAtUnixSeconds to buildSessionPolicy().

### SESSION\_APPROVAL\_MISMATCH

**Session approval does not match**

* **HTTP status:** 409
* **Retryable:** no
* **Cause:** The approval was made for another account, permission id or mode.
* **Fix:** Re-run prepare, have the owner sign again, then activate.

### SESSION\_EXPIRED

**Session expired**

* **HTTP status:** 410
* **Retryable:** no
* **Cause:** The session's expiry has passed.
* **Fix:** Grant a new session.

### SESSION\_NONE

**No active session**

* **HTTP status:** 409
* **Retryable:** no
* **Cause:** The user has not granted a session, or it was revoked.
* **Fix:** Ask the user to grant a session first.

## Bundler

### BUNDLER\_AA\_FAILED

**EntryPoint rejected the UserOperation**

* **HTTP status:** 502
* **Retryable:** no
* **Cause:** The EntryPoint reported FailedOp with an AAxx code during validation or execution.
* **Fix:** Read the AAxx code: AA21 prefund missing, AA23 signature or validation reverted, AA25 invalid nonce, AA31/AA33/AA34 paymaster problems.

### BUNDLER\_UNREACHABLE

**Bundler or paymaster is unreachable**

* **HTTP status:** 502
* **Retryable:** yes
* **Cause:** The request to the bundler or paymaster URL failed before any response.
* **Fix:** Check PEPU\_BUNDLER\_URL and PEPU\_PAYMASTER\_URL. Use checkSponsorship() to see which one failed.

## Paymaster and sponsorship

### PAYMASTER\_API\_ERROR

**Paymaster API request failed**

* **HTTP status:** 502
* **Retryable:** no
* **Cause:** The paymaster API returned an error that has no more specific PEPU code.
* **Fix:** Read error.details (HTTP status and the service's error code) and the OpenAPI spec for that route.

### PAYMASTER\_CAP

**Sponsorship cap reached**

* **HTTP status:** 429
* **Retryable:** yes
* **Cause:** A daily, per-sender or per-operation sponsorship cap was hit.
* **Fix:** Wait for the cap window to reset, or raise the project's daily and sender limits.

### PAYMASTER\_DENIED

**Paymaster denied the sponsorship**

* **HTTP status:** 403
* **Retryable:** no
* **Cause:** The paymaster rejected the credential or the sender (for example unknown\_or\_invalid\_app\_credential or sender\_not\_owned\_by\_token\_user).
* **Fix:** Check the app credential or token, and that the smart account belongs to the user whose access token you sent.

### PAYMASTER\_DESTINATION\_NOT\_ALLOWED

**Paymaster refused the call destination**

* **HTTP status:** 403
* **Retryable:** no
* **Cause:** The UserOperation targets a contract that is not on the project's target allowlist.
* **Fix:** Add the contract to the project's targets, or sponsor only calls to allowed targets.

### PAYMASTER\_FREE\_TIER\_UNAVAILABLE

**Free tier cannot sponsor this operation**

* **HTTP status:** 429
* **Retryable:** yes
* **Cause:** The free tier is disabled, its pool is empty, or the operation is larger than the per-op cap.
* **Fix:** Deposit into your own project and use its credentials, or retry later.

### PAYMASTER\_IDENTITY\_REQUIRED

**A verified Privy account is required**

* **HTTP status:** 401
* **Retryable:** no
* **Cause:** The free tier (and any project with requireIdentity on) only sponsors users with a verified Privy access token.
* **Fix:** Send the user's Privy access token as Authorization: Bearer (or context.privyAccessToken for ERC-7677).

### PAYMASTER\_NO\_BALANCE

**Sponsorship project has no balance**

* **HTTP status:** 429
* **Retryable:** yes
* **Cause:** The project's paymaster deposit cannot cover this operation.
* **Fix:** Deposit more PEPU to the project, then retry.

### PAYMASTER\_ORIGIN\_NOT\_ALLOWED

**Paymaster refused the request origin**

* **HTTP status:** 403
* **Retryable:** no
* **Cause:** The request Origin is not on the project's allowlist.
* **Fix:** Add the exact origin (scheme, host and port) to the project's allowed origins.

### PAYMASTER\_PROJECT\_NOT\_CLAIMED

**Sponsorship project is not claimed on-chain**

* **HTTP status:** 409
* **Retryable:** no
* **Cause:** Deposits can sit in an unclaimed project, but nothing is sponsored until its owner has claimed it on-chain (the contract reports ProjectNotClaimed, the service project\_not\_claimed\_onchain).
* **Fix:** Prove the Privy app (requestClaimAttestation from @pepu-chain/sdk/paymaster/server), call claimProject, then configureProject (setTargets, setDailyLimit, setSenderDailyLimit).

### PAYMASTER\_PROJECT\_OWNER\_CHANGED

**Project owner changed since the credentials were issued**

* **HTTP status:** 403
* **Retryable:** no
* **Cause:** The on-chain owner of the project is no longer the address the off-chain credentials were issued to (an ownership transfer or re-claim completed).
* **Fix:** As the new owner, sign in with SIWE, register the project again and rotate the client token and server key.

### PAYMASTER\_PROJECT\_PAUSED

**Sponsorship project is paused**

* **HTTP status:** 403
* **Retryable:** no
* **Cause:** The project owner paused sponsorship on-chain.
* **Fix:** The owner can resume it with setPaused(projectId, false).

### PAYMASTER\_RATE\_LIMITED

**Paymaster API rate limit**

* **HTTP status:** 429
* **Retryable:** yes
* **Cause:** Too many requests to the paymaster API from this IP or account.
* **Fix:** Back off for the Retry-After interval (error.details.retryAfterSeconds when present).

### PAYMASTER\_SESSION\_REQUIRED

**Paymaster owner session missing or expired**

* **HTTP status:** 401
* **Retryable:** no
* **Cause:** Owner endpoints need a SIWE session token (1 h lifetime) for the project's current on-chain owner.
* **Fix:** Call loginWithWallet() on the paymaster API client, then retry.

### PAYMASTER\_UNREACHABLE

**Paymaster service is unreachable**

* **HTTP status:** 502
* **Retryable:** yes
* **Cause:** The request to the paymaster service failed before any response (network error, DNS failure or timeout).
* **Fix:** Check PEPU\_PAYMASTER\_URL and your network. The hosted service is <https://paymaster.pepeunchained.com>; run checkSponsorship() or probePaymaster() for detail.

## Transactions and chain

### MULTICALL3\_CANONICAL\_ADDRESS

**Canonical Multicall3 address used on PEPU**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** PEPU's Multicall3 is not at the canonical 0xcA11...CA11 address.
* **Fix:** Use getMulticall3() or pepuMulticall() from @pepu-chain/sdk, or the pepuMainnet chain object, which carries the right address.

### TX\_GAS\_UNDERSHOOT

**Gas limit too low**

* **HTTP status:** 502
* **Retryable:** yes
* **Cause:** Nitro gas estimation undershoots on PEPU: the L1 data component is not covered by the plain estimate.
* **Fix:** Add headroom to the estimate, 20% via withGasLimitBuffer() from @pepu-chain/sdk/session.

### TX\_NONCE\_RACE

**Nonce conflict**

* **HTTP status:** 409
* **Retryable:** yes
* **Cause:** Two transactions raced for one nonce, or a replacement was underpriced.
* **Fix:** Serialize sends per account (a lock), re-read the pending nonce, and retry.

### TX\_REVERTED

**Transaction reverted**

* **HTTP status:** 502
* **Retryable:** no
* **Cause:** The contract call reverted.
* **Fix:** Decode the revert reason with explainError() and check arguments, allowances and balances.

### UNKNOWN

**Unknown error**

* **HTTP status:** 500
* **Retryable:** no
* **Cause:** The error did not match any known PEPU failure.
* **Fix:** Read the original message. Run pepu\_known\_gotchas in the MCP server, or search the docs.

## Paymaster denial reasons

The policy service answers a denied request with a `reason` string. The SDK maps every reason to one of the codes above with `mapPaymasterReason(reason)` and `paymasterReasonToError(reason, message)` from `@pepu-chain/sdk/paymaster`. An unknown reason (a newer service) maps to `PAYMASTER_DENIED`. Reasons marked v1 come from the v1 paymaster; the rest come from the v2 policy service, which is built but not deployed.

| Reason                              | Service | Maps to                                                                   | Retryable |
| ----------------------------------- | ------- | ------------------------------------------------------------------------- | --------- |
| `unknown_or_invalid_app_credential` | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `app_suspended`                     | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `invalid_or_expired_token`          | v2      | [`AUTH_INVALID_TOKEN`](#AUTH_INVALID_TOKEN)                               | no        |
| `sender_not_owned_by_token_user`    | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `calldata_decode_failed`            | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `project_not_claimed_onchain`       | v2      | [`PAYMASTER_PROJECT_NOT_CLAIMED`](#PAYMASTER_PROJECT_NOT_CLAIMED)         | no        |
| `project_owner_changed`             | v2      | [`PAYMASTER_PROJECT_OWNER_CHANGED`](#PAYMASTER_PROJECT_OWNER_CHANGED)     | no        |
| `project_paused`                    | v2      | [`PAYMASTER_PROJECT_PAUSED`](#PAYMASTER_PROJECT_PAUSED)                   | no        |
| `project_balance_exhausted`         | v2      | [`PAYMASTER_NO_BALANCE`](#PAYMASTER_NO_BALANCE)                           | no        |
| `project_daily_limit_reached`       | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `project_user_cap_exceeded`         | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `project_identity_required`         | v2      | [`PAYMASTER_IDENTITY_REQUIRED`](#PAYMASTER_IDENTITY_REQUIRED)             | no        |
| `project_origin_not_allowed`        | v2      | [`PAYMASTER_ORIGIN_NOT_ALLOWED`](#PAYMASTER_ORIGIN_NOT_ALLOWED)           | no        |
| `project_sender_limit_reached`      | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `project_sender_limit_not_set`      | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `account_deployment_disabled`       | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `target_not_allowed_onchain`        | v2      | [`PAYMASTER_DESTINATION_NOT_ALLOWED`](#PAYMASTER_DESTINATION_NOT_ALLOWED) | no        |
| `destination_not_allowed_for_app`   | v2      | [`PAYMASTER_DESTINATION_NOT_ALLOWED`](#PAYMASTER_DESTINATION_NOT_ALLOWED) | no        |
| `free_tier_disabled`                | v2      | [`PAYMASTER_FREE_TIER_UNAVAILABLE`](#PAYMASTER_FREE_TIER_UNAVAILABLE)     | no        |
| `free_tier_identity_required`       | v2      | [`PAYMASTER_IDENTITY_REQUIRED`](#PAYMASTER_IDENTITY_REQUIRED)             | no        |
| `free_tier_user_daily_exceeded`     | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `free_tier_user_hourly_exceeded`    | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `free_tier_count_exceeded`          | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `free_tier_sender_limit_reached`    | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `free_pool_empty`                   | v2      | [`PAYMASTER_FREE_TIER_UNAVAILABLE`](#PAYMASTER_FREE_TIER_UNAVAILABLE)     | no        |
| `free_pool_op_too_large`            | v2      | [`PAYMASTER_FREE_TIER_UNAVAILABLE`](#PAYMASTER_FREE_TIER_UNAVAILABLE)     | no        |
| `chain_read_failed`                 | v2      | [`PAYMASTER_API_ERROR`](#PAYMASTER_API_ERROR)                             | yes       |
| `gas_limits_out_of_bounds`          | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `fee_out_of_bounds`                 | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `fee_above_onchain_cap`             | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `reservation_cap_exceeded`          | v2      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `rate_limited`                      | v2      | [`PAYMASTER_RATE_LIMITED`](#PAYMASTER_RATE_LIMITED)                       | yes       |
| `malformed_request`                 | v2      | [`PAYMASTER_DENIED`](#PAYMASTER_DENIED)                                   | no        |
| `destination_not_globally_allowed`  | v1      | [`PAYMASTER_DESTINATION_NOT_ALLOWED`](#PAYMASTER_DESTINATION_NOT_ALLOWED) | no        |
| `user_hourly_count_cap_exceeded`    | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `user_daily_count_cap_exceeded`     | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `user_lifetime_count_cap_exceeded`  | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `user_hourly_spend_cap_exceeded`    | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `user_daily_spend_cap_exceeded`     | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `user_lifetime_spend_cap_exceeded`  | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `app_daily_spend_cap_exceeded`      | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `app_lifetime_spend_cap_exceeded`   | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |
| `global_circuit_breaker_tripped`    | v1      | [`PAYMASTER_CAP`](#PAYMASTER_CAP)                                         | no        |

## Bundler and AA failures

A bundler rejection surfaces as `BUNDLER_AA_FAILED` with the EntryPoint's `AAxx` code in the message (for example `AA21 didn't pay prefund`, `AA25 invalid account nonce`, `AA33 reverted` for a paymaster revert). A network or CORS failure surfaces as `BUNDLER_UNREACHABLE`. The JSON-RPC error table for the bundler is on [Bundler JSON-RPC API](/infrastructure/api.md); the paymaster HTTP error table is on [REST API v1](/infrastructure/rest-api-v1.md) and [REST API v2](/infrastructure/rest-api-v2.md).

## What to expect

* `pepu_health_check` and `pepu_sponsorship_status` probe the hosted bundler and the paymaster service base by default; set the variables to point elsewhere.
* `node scripts/check-docs-parity.mjs` verifies the addresses and counts on the docs pages against the SDK registry.

## Common failures

* You see a code that is not on this page: you are on an older SDK. Upgrade `@pepu-chain/sdk`, or run the error text through `pepu_explain_error`.
* You see `UNKNOWN`: nothing in the catalog matched. Read the original `cause`, and see [Troubleshooting](/troubleshooting/troubleshooting.md).

## Related

* [SDK Error Catalog](/sdk/errors.md)
* [Troubleshooting](/troubleshooting/troubleshooting.md)
* [Policy, Caps and the Circuit Breaker](/infrastructure/policy-and-caps.md)
* [MCP Tool Reference](/mcp/tools.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.pepeunchained.com/reference/errors.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
