> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://docs.prividium.com/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

This page lists common errors and how to resolve them. For SDK and RPC patterns, see
[Building Web Applications](/developers/applications/building-web-applications).

## Quick diagnosis

Run the following command to automatically check your Prividium configuration, API connectivity, and authentication
setup from the command line:

```bash
npx prividium doctor -r {{PRIVIDIUM_API_URL}} -u {{USER_PANEL_URL}}
```

The `-r` flag points to the Prividium API and `-u` to the user panel URL used for browser-based authentication. The
`doctor` command validates connectivity, OIDC settings, and network reachability, and reports any issues it finds.

## Verify user and configuration

Call `GET /api/profiles/me` with a valid session (Bearer token) to confirm the authenticated user's identity, assigned
roles, and linked wallets. Mismatched roles or missing wallet associations cause many access-denied or
transaction-not-authorized issues. Use this as a sanity check before debugging permissions.

**troubleshooting.ts**

```typescript
    const response = await fetch(`${PRIVIDIUM_API_URL}/api/profiles/me`, {
        method: 'GET',
        headers: { Authorization: `Bearer ${token}` }
    });
    if (!response.ok) throw new Error(`Profile request failed: ${response.status}`);
    const profile = await response.json();
    // Check profile.roles and profile.wallets
```

## RPC -32001 Forbidden or access denied to a function

The RPC returns HTTP 200 with `error.code -32001` when the user is authenticated but not allowed to call that contract
or method. See [RPC Error Codes](/rpc/rpc-error-codes) for the full code reference.

**Best practice:** Have an administrator check [Contract Permissions](/configuring/contracts/permissions):
(1) Contract is registered and the function is listed. (2) Function permission level is not Forbidden and matches the
intended access (All Users, Check Role, or Restrict Argument). (3) If Check Role is used, the user has one of the
allowed roles (check Users in the Admin Dashboard).

## 401 Unauthorized

Missing or invalid session or token. Use the authenticated transport for reads and ensure the token is sent with
requests. For causes and fix with code examples, see
[Building Web Applications – Error Handling](/developers/applications/building-web-applications#error-handling).

## API key errors

When a request sends an `X-API-Key` header that Prividium cannot use, `/rpc` returns error code `-32090` and REST routes
return HTTP 401 with code `UNAUTHORIZED_ERROR`. The message says what went wrong:

| Message                                                                                        | Cause                                                                                                                                                      |
| ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Malformed API key: expected priv_sk_ followed by 64 letters or digits (72 characters), got N` | The header value is not a well-formed key. `N` is the length received. Typical causes are an extra or missing character, or surrounding quotes.            |
| `Multiple X-API-Key headers`                                                                   | The request carried more than one `X-API-Key` header. Send exactly one.                                                                                    |
| `API key rejected`                                                                             | The key is unknown, expired or revoked, cannot be used on this route, or the request IP is not on the app's IP whitelist. The response does not say which. |

On `/rpc`, the error `data` helps you match the request to the admin panel:

* `keyPrefix`: the first 12 characters of the key you sent. Compare it with the **Key Prefix** column on the M2M app's
  **API Keys** tab.
* `clientIp`: the source IP Prividium saw. Add it to the app's IP whitelist if it is missing. Prividium omits it when the
  address is private or internal, for example when a proxy in front of the API forwards the request.

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32090,
    "message": "API key rejected",
    "data": { "clientIp": "203.0.113.7", "keyPrefix": "priv_sk_Ab12" }
  }
}
```

For more detail about `API key rejected`, ask an administrator to check **Admin panel → Audit Logs** for sampled API-key authentication failures. Each entry records the reason and the IP of the sampled request.

Failures are sampled per source IP when no active key is recognized, or per recognized key and reason, subject to per-replica limits. An entry may describe an earlier request from another IP, and your request may have no entry. Sampling does not count every failure or list every source IP. See [API-Key Failure Audits](/configuring/applications/rate-limiting#api-key-failure-audits).

A request with neither an `X-API-Key` header nor a session token is anonymous. Gated methods then return `-32090` with
the message `Authentication required: send an X-API-Key header or a session token`. Public methods such as `eth_chainId` still work.

### Check that an API key works

`eth_chainId` is public, so it succeeds with or without a key. Call a gated method such as `eth_getBalance` instead:

```bash
curl -s "$PRIVIDIUM_RPC_URL" \
  -H 'content-type: application/json' \
  -H "X-API-Key: $PRIVIDIUM_M2M_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0x0000000000000000000000000000000000000001","latest"]}'
```

* No key: `-32090` with the message `Authentication required: send an X-API-Key header or a session token`.
* Malformed or rejected key: `-32090` with one of the messages above.
* Valid key: a balance, or `-32001 Forbidden` when the app may not read that address. Both confirm that the key
  authenticated.

## Transaction not authorized or wallet errors

Transaction authorizations are required for write operations via the Per-User RPC. Call `authorizeTransaction` before
sending; ensure the wallet address is linked to the user in the Admin Panel. Errors like "User is not authorized to
perform this action" or "Wallet address is not associated with the user" mean the authorization check or user–wallet
link failed. See [Per-User RPC](/rpc/per-user-rpc) for transaction authorization lifecycle and
[Building Web Applications – Error Handling](/developers/applications/building-web-applications#error-handling)
for the 401-on-write and pre-fetch pattern.

## Other common errors

* **"RPC method eth\_call requires an account to be provided for the client"** — Pass `account` to the public client used
  for contract reads. See
  [Building Web Applications – Error Handling](/developers/applications/building-web-applications#error-handling).
* **"Wallet is on wrong network"** — Configure the wallet with the Per-User RPC URL via `addNetworkToWallet()`. See
  [Building Web Applications – Error Handling](/developers/applications/building-web-applications#error-handling).
