> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rhinestone.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Handle SDK errors and diagnose account, session, recovery, and intent failures.

Import typed errors and guards from `@rhinestone/sdk/errors`. Orchestrator errors include a `code`, `statusCode`, and `traceId`; include the trace ID when contacting support.

```ts theme={null}
import {
  isAccountError,
  isExecutionError,
  isOrchestratorError,
  isRateLimited,
  isRetryable,
  isSimulationFailed,
  isValidationError,
} from "@rhinestone/sdk/errors";

try {
  const prepared = await rhinestoneAccount.prepareTransaction(transaction);
  const signed = await rhinestoneAccount.signTransaction(prepared);
  const result = await rhinestoneAccount.submitTransaction(signed);
  await rhinestoneAccount.waitForExecution(result);
} catch (error) {
  if (isRateLimited(error)) {
    scheduleRetry(error.retryAfter);
  } else if (isSimulationFailed(error)) {
    console.error(error.category, error.errorName, error.simulations);
  } else if (isValidationError(error)) {
    console.error(error.issues);
  } else if (isRetryable(error)) {
    scheduleRetry();
  } else if (isOrchestratorError(error)) {
    console.error(error.code, error.traceId);
  } else if (error instanceof Error) {
    console.error(error.message);
  }
}
```

This snippet continues an existing account and transaction setup. Implement `scheduleRetry` in your application; `retryAfter` is an optional string header value, so handle both delay-seconds and HTTP-date formats.

Retry only an idempotent operation. Do not resubmit a signed transaction unless you have confirmed that the previous submission was not accepted.

## Account configuration errors

| Error | Cause | Fix |
| - | - | - |
| `OwnersFieldRequiredError` | A smart account was created without `owners`. | Pass a supported owner set in `createAccount({ evm: { owners } })`. |
| `Eip7702AccountMustHaveEoaError` | An EIP-7702 account has no EOA signer. | Pass the delegated EOA in `evm.eoa`. |
| `Eip7702NotSupportedForAccountError` | The selected account implementation cannot use EIP-7702. | Choose a supported implementation or remove EIP-7702. |
| `EoaAccountMustHaveAccountError` | EOA mode has no signer account. | Pass the signer in `evm.eoa` and set `evm.account.type: 'eoa'`. |
| `WalletClientNoConnectedAccountError` | A wallet client has no default connected account. | Connect the wallet and construct the client with an account. |
| `EoaSigningMethodNotConfiguredError` | The EOA adapter is missing a required signing callback. | Implement the named signing method. |
| `EoaSigningNotSupportedError` | EOA mode was asked to create a packed smart-account signature. | Sign with the EOA directly or use a smart account. |
| `PasskeyConfigurationNotInstallableError` | The passkey owner set cannot initialize a new account. | Check the passkey count, threshold, and account implementation. |
| `ModuleInstallationNotSupportedError` | The account implementation cannot install the requested module. | Use a modular account or remove the module configuration. |
| `DefaultValidatorAlreadyInitializedError` | Code tried to enable ECDSA twice. | Use `addOwner`, `removeOwner`, or `changeThreshold`. |
| `Eip712DomainNotAvailableError` | The account cannot expose the domain required for typed-data signing. | Use a supported validator or signing path. |
| `AccountConfigurationNotSupportedError` | The selected account and module combination is unsupported. | Change the configuration before deployment. |
| `FactoryArgsNotAvailableError` | Deployment data could not be derived. | Confirm the account configuration; report a reproducible SDK issue if it persists. |
| `SigningNotSupportedForAccountError` | The account implementation cannot sign messages. | Use a supported smart-account validator or the account's native signer. |

Catch account implementation errors with `isAccountError(error)`. For composite configuration and VM capability failures, use the separately exported `isAccountCapabilityError` guard:

| Error | Fix |
| - | - |
| `InvalidAccountConfigError` | Put EVM configuration under `evm`; do not pass legacy top-level owners or provider fields. |
| `AccountVmNotConfiguredError` | Configure the requested VM and use `getAddress('evm')` for EVM guides. |
| `UnsupportedAccountCapabilityError` | Use a managed entry for the requested VM. Receivers cannot sign; Smart Sessions and EVM guardian recovery require managed EVM accounts. Solana authority management requires a managed Solana owner. |

## Transaction and signing errors

| Error | Cause | Fix |
| - | - | - |
| `Eip7702InitSignatureRequiredError` | Transaction preparation needs an EIP-7702 initialization signature, even for an already deployed account. | Call `signEip7702InitData()` and pass the result as `eip7702InitSignature` when preparing. |
| `OrderPathRequiredForIntentsError` | Submission did not originate from a prepared intent. | Call `prepareTransaction`, then sign and submit its result. |
| `QuoteNotInPreparedTransactionError` | The chosen intent ID does not belong to the prepared response. | Re-prepare or select an ID from `prepared.quotes.all`. |
| `InvalidSourceCallsError` | Source calls cannot be mapped to the selected funding source. | Use singular `source.chain`, `source.token`, and `source.calls`; `provides` must match the selected token. |
| `SignerNotSupportedError` | A guardian signer was used with the intent transaction flow. | Send a UserOperation for guardian recovery. |
| `UnknownOwnerError` | Independent signing used an account outside the configured owner set. | Pass an exact configured owner and the matching MFA validator ID. |
| `InvalidOwnerSigningOptionsError` | `validatorId` was omitted, unnecessary, or pointed at the wrong MFA factor. | Pass it only for the factor containing that owner. |
| `MismatchedOwnerSignaturesError` | Owner contributions are duplicated or cover different prepared transactions, quotes, or slots. | Redistribute one prepared payload and collect signatures again. |
| `InsufficientOwnerSignaturesError` | The assembled contributions do not meet the account threshold. | Collect the missing signatures before `assembleTransaction`. |
| `IndependentSigningNotSupportedError` | The selected validator or transaction shape cannot be assembled independently. | Use the standard `signTransaction(prepared)` flow. |
| `IntentFailedError` | A submitted intent reached a failed terminal state. | Inspect `error.context.operations` and `error.context.refunds`; operations are CAIP-2 chain groups with `items[]` and native transaction references. A refunded intent is still failed. Reconcile effects before preparing a retry. |

Catch the category with `isExecutionError(error)`.

### Prepared artifacts and proofs

Use the exported `isExecutionError` guard for these diagnostics. `InvalidPreparedTransactionError`, `UnsupportedSigningRequestError`, `IncompleteIntentProofsError`, and `MismatchedIntentProofError` are thrown internally but their constructors are not exported from `@rhinestone/sdk/errors` in this revision. Do not import internal paths.

| Error | Fix |
| - | - |
| `InvalidPreparedTransactionError` | Earlier SDK/wire artifacts cannot be signed or submitted. Reconcile any original submission first, then prepare again and collect fresh signatures. Do not patch stored artifacts or silently re-quote. |
| `UnsupportedSigningRequestError` | Inspect the request index and payload kind. Use a compatible signing path or change the request; do not drop the slot. |
| `IncompleteIntentProofsError` | Supply a proof for every ordered `quote.signingRequests` entry. Normal `signTransaction` collects delegation proofs; independent assembly takes indexed proofs in `{ proofs }`. |
| `MismatchedIntentProofError` | Contributions must bind the selected intent ID, exact request set, and request index. Do not mix re-quotes or reorder proofs. |
| `UnsupportedSponsorshipApprovalError` | The approval input cannot bind the quote request exactly. Inspect the indicated field and remove the unsupported option or correct the mismatch. Do not bypass application authorization. |

Persist the complete prepared object, including `request`, with a serialization format that preserves `bigint` values. Keep returned owner contributions opaque. See [Custom signing](/wallets/custom-signer/signing/custom-signing).

### Funding and quote requirements

Use `destination` for execution or delivery and select one funding chain/token in `source`. Delivery always requires a source; user-paid execution needs a fee token. Sufficiently sponsored no-delivery EVM or Solana instruction execution can omit it. Solana authority changes always omit the source and are gas-sponsored. A portfolio read does not automatically select or aggregate funding.

Inspect the selected quote's `requirements[]`, including approval and wrap requirements. These are disclosures, not automatic SDK actions. Resolve prerequisites explicitly and prepare again if the inputs or state change. `maxAmount` caps observed source balance; auxiliary funds are added after the cap.

JWT approval occurs during prepare/quote. Upgrade backend helpers and runtime schemas before clients, require `sdk-3.0.0-caucasus`, and authorize the applicable `account.evm` or `account.svm` entry, `source`, `destination`, and `options`. A bound digest is not a sponsorship policy. See [Security](/wallets/custom-signer/integration/security).

## API and quote errors

| Error | Action |
| - | - |
| `ValidationError` | Inspect `issues` and correct the named request fields. |
| `UnauthorizedError` | Check that the API key is valid and sent through `auth: { mode: 'apiKey', apiKey }`. |
| ``Top-level `apiKey` was removed`` | Replace `new RhinestoneSDK({ apiKey })` with `auth: { mode: 'apiKey', apiKey }`. |
| `ForbiddenError` | Confirm that the project and requested operation are allowed. |
| `KeyScopeDeniedError` | Compare `scope`, `required`, and `actual`, then widen the key scope if appropriate. |
| `InsufficientLiquidityError` | Inspect `unfillable` and `availableIntents`; reduce or change the requested assets. |
| `SponsorLimitExceededError` | Raise the configured sponsorship cap or make the intent cheaper. Adding balance does not change the cap. |
| `InsufficientSponsorBalanceError` | Top up the sponsorship balance for the categories in `failedCategories`. |
| `SimulationFailedError` | Inspect `category`, `errorName`, `errorArgs`, and `simulations`. Retry only when `retryable` is true. |
| `RateLimitedError` | Wait for `retryAfter`. Rate limits are not included in `isRetryable`. |
| `SettlementQuoteError` | Re-prepare later or change the route inputs. |
| `SettlementExecutionError` | Check the returned intent status before retrying. |
| `ExternalServiceTimeoutError` | Retry an idempotent request with backoff. |
| `RelayerMarketUnavailableError` | Retry later with backoff. |
| `InternalServerError` | Retry an idempotent request and report the `traceId` if it persists. |
| `NotFoundError` | Check the requested intent or resource ID. |
| `ConflictError` | Refresh state before retrying the operation. |
| `UnprocessableContentError` | Inspect `details`; the request is valid JSON but cannot be fulfilled as submitted. |

`isRetryable(error)` returns true for internal errors, upstream timeouts, unavailable relayers, and simulation failures explicitly marked retryable. Use `isSponsorError`, `isSponsorLimitExceeded`, and `isInsufficientSponsorBalance` to distinguish sponsorship failures. Follow [sponsorship setup](/transactions/sponsorship/set-up) for balance and policy configuration.

## Registry errors

| Error | Fix |
| - | - |
| `UnsupportedChainError` | Choose a chain returned by the current SDK chain catalog. |
| `UnsupportedTokenError` | Use a supported token for `source.token` or `destination.token` on its chain. |

These are local SDK validation errors, not Orchestrator responses.

## Solana failures

Native Solana transactions use the same prepare/sign/submit/wait lifecycle. Preserve the complete prepared artifact and its ordered signing requests; do not convert it into a UserOperation or replace its proof with a signature from an Ed25519 wallet. The managed owner must be one viem secp256k1 or WebAuthn account.

| Error or result | Action |
| - | - |
| `ManagedSolanaAccountNotSupportedError` | Confirm that your SDK environment and service endpoint support managed Solana. A chain descriptor alone does not enable an environment or route. |
| `SolanaAccountNotCreatedError` | Restore the saved `id` and `swig` and deploy with `deploy('solana', chain, { swigId: id })`. Verify the intended root before funding; do not prefund an undeployed predictable address. |
| `SolanaQuoteExpiredError` | Reconcile any prior submission, then prepare again and collect fresh signatures. Do not reuse the expired signed quote. |
| `InvalidSolanaTransactionArtifactError` | Restore the complete, unmodified artifact with bigint-preserving serialization. Reconcile a previous submission before re-preparing; do not patch quote or proof fields. |
| `UnsupportedAccountCapabilityError` | Inspect the named field: use Solana `instructions` or `authority`, not EVM `calls`, sessions, or UserOperations. Enrollment needs a valid public key, not an EVM address. |
| `getAuthorityStatus(change)` returns `notApplied` | The requested change is not in place. Confirm the chain and key, reconcile an uncertain submission, then prepare the specific authority change if still needed. |
| `getAuthorityStatus(change)` returns `conflict` | The key exists with different or unreadable permissions. Inspect the returned role and actual on-chain permission; do not treat it as ready or retry an add blindly. |

Import the error constructors and `isSolanaAccountNotCreated`, `isSolanaAuthorityChangeRefused`, `isSolanaQuoteExpiredError`, and `isInvalidSolanaTransactionArtifactError` guards from `@rhinestone/sdk/errors`. `getAuthorityStatus` only checks one authority change, not global deployment or owner readiness. Deployment returning `true` can also mean an existing Swig without checking your configured owner.

### Authority change refusals

`SolanaAuthorityChangeRefusedError` exposes a typed, optional `reason` and role metadata. Handle unknown reasons as refusals; retain redacted `issues` and `traceId` for diagnosis.

| `reason` | Action |
| - | - |
| `acting_permission` | Use a signer whose on-chain role has `all` or `manageAuthority`. Replacing a local owner configuration does not grant a role. |
| `authority_exists` | Check the exact change with `getAuthorityStatus`; an existing key with different permissions is a conflict. |
| `authority_not_found` | Confirm the key and cluster before removing; reconcile state instead of repeatedly resubmitting. |
| `authority_ambiguous` or `unsupported_authority` | Inspect the on-chain roles and contact support; do not guess a role ID or rewrite the request. |
| `root_role` | The root is permanent. If compromised, migrate assets to a new wallet; adding a replacement does not revoke it. |
| `lockout` | Keep an authority manager installed. Add and verify a replacement manager before removing a non-root manager. |

See [Solana recovery setup](/wallets/custom-signer/recovery/set-up#solana-enroll-a-recovery-key). Authority changes and deployments require separately authenticated sponsorship policies, not an unrestricted token-delivery policy. Network availability depends on the environment; mainnet support remains route-dependent.

## EVM session key failures

| Symptom | Cause | Fix |
| - | - | - |
| `No session configured for chain …` | A per-chain signer map is missing a required EVM source or destination chain. | Add that chain's resolved session to `signers.sessions`. |
| `Cannot sign a chain-agnostic intent payload with a smart session` | One signature would need to validate on legs from several chains. | Split the operation into per-chain intents. |
| `This Smart Session has signing disabled` | `signMessage` or `signTypedData` used a session with `signing.mode: 'disabled'`. | Use account owners or create a session with the required signing capability. |
| `Scoped Smart Session signing requires safe ERC-7739 emission` | Direct scoped typed-data signing is not available in SDK 3.0.0. | Use account owners or an unrestricted session only when its risk is acceptable. |
| A restricted, swap-scoped, or cross-chain permit session rejects an intent as an invalid signature | The route added fee or gas-refund calls that the session does not authorize. | Sponsor the intent. For a permit session, set `allowFees` on the permit; otherwise authorize every required call explicitly. |
| `REMOVED_CLAIM_POLICIES_INPUT` | The session definition sets `claimPolicies`, even as `undefined` or empty. | Delete the key and use `crossChainPermits`. Custom-spender claim policies have no replacement input. |
| `RETIRED_PERMIT2_LAYER` | A permit names the retired `ECO` layer. | Use `ECO_IE`. |
| `NO_LAYER_CAN_SETTLE`, or a refusal naming a `layer` | Default coverage found no layer for the permit, or an explicit `settlementLayers` list names a layer that cannot settle it. | Read the refusal's reason, adjust the permit, or name different layers. |
| `LAYER_REQUIRES_ONE_TIME_USE` | The permit names `OFT` or `LZ` without `oneTimeUse`. | Add `oneTimeUse` or name other layers. |
| `PERMIT2_ROUTE_NEEDS_BOUND` | A reusable scoped `ACROSS` permit is on a chain without the Permit2SenderPolicy. | Add `oneTimeUse`, or create the session on a chain with the policy. |
| `RECIPIENT_NEEDS_ACCOUNT` | A layer pins the recipient to the account in calldata, but the definition has no `account`. | Set `account` on the session definition. |
| `oneTimeUse: no OneTimeUseIdPolicy is deployed on chain …` | The session's chain has no default OneTimeUseIdPolicy. | Use a chain with the policy, or drop `oneTimeUse`. |
| `… its maxAmount is a lifetime budget: signing its enable again would reset that budget …` | `getSessionDetails` received an enabled session with a lifetime `maxAmount` budget. | Leave it out, or pass `{ allowBudgetReset: true }` only to reset the budget deliberately. |
| `This smart session requires an explicit source for its oneTimeUse burn or pre-claim restrictions` | A one-time-use session's intent has no explicit `source`. | Pass `source` to `prepareTransaction`. |
| Activation fails after rebuilding session data | The session definition, policy addresses, order, or session index differs from the signed details. | Persist and reuse the exact resolved session and `hashesAndChainIds`. |
| A restricted session unexpectedly retains older permissions | Two sessions for the same signer reused a permission ID. | Use `saltMode: 'strict'` for new restricted sessions; enabling it changes the ID, so do not apply it to an existing signed session. |

See [Multi-chain sessions](/wallets/session-keys/custom-setup/multi-chain-sessions) and [Restrict a session](/wallets/session-keys/custom-setup/restrict-a-session) for the required shapes. Call `rhinestone.validateSession` to list every refusal for a session definition at once; see [Validate a definition](/wallets/session-keys/custom-setup/create-a-session#validate-a-definition).

## EVM guardian recovery failures

| Symptom | Cause | Fix |
| - | - | - |
| Guardian signing fails in `prepareTransaction`, `signMessage`, or `signTypedData` | Guardians are valid only for recovery UserOperations. | Use `sendUserOperation` with one recovery call. |
| Recovery reverts when calls are batched | The recovery validator authorizes one account execution per UserOperation. | Submit one returned call at a time, in order. |
| `CredentialAlreadyExists` during passkey recovery | `currentCredentials` omitted an installed passkey. | Rebuild the recovery with the complete current credential set. |
| Bundler submission fails or no bundler is configured | Recovery runs through ERC-4337. | Configure a production bundler and retry only the call that did not execute. |
| Nexus recovery cannot change owners | The account does not use the same Ownable V0 module in its account and target-owner configuration. | Migrate while the current owner is available, then keep the module address consistent. |

Follow [Recover an account](/wallets/custom-signer/recovery/recover-an-account) for the ordering constraints.

## Report a persistent failure

Capture:

* the SDK version (`3.0.0` for these examples)
* the error class, message, `code`, and `traceId`
* the account address and chain IDs
* the intent ID or UserOperation hash
* redacted request parameters and per-operation status

Never include private keys, passkey material, API keys, or JWTs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.