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

# Error Handling

The Openfort SDK provides a comprehensive error handling system with typed error classes and error codes to help you handle specific failure scenarios gracefully.

## Error Classes

All Openfort errors extend the base `OpenfortError` class. Import the error classes you need:

```typescript
import {
  OpenfortError,
  AuthenticationError,
  AuthorizationError,
  ConfigurationError,
  OAuthError,
  OTPError,
  RecoveryError,
  RequestError,
  SessionError,
  SignerError,
  UserError,
} from '@openfort/openfort-js'
```

### OpenfortError

The base error class that all other Openfort errors extend. Contains common properties:

```typescript
class OpenfortError extends Error {
  error: string              // Error code for programmatic handling
  error_description: string  // Human-readable error description
  statusCode?: number        // HTTP status, when the error came from an API response
  requestId?: string         // Request ID (x-request-id) of the failed API call
  version: string            // SDK version that produced the error
  docsUrl?: string           // Documentation page for this failure, when available
}
```

### AuthenticationError

Thrown when authentication fails (invalid credentials, expired tokens, etc.).

```typescript
try {
  await openfort.auth.logInWithEmailPassword({ email, password })
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.log('Authentication failed:', error.message)
    // Show login error to user
  }
}
```

### AuthorizationError

Thrown when the user lacks permission to perform an action.

```typescript
try {
  await openfort.embeddedWallet.exportPrivateKey()
} catch (error) {
  if (error instanceof AuthorizationError) {
    console.log('Not authorized:', error.message)
    // Prompt user to authenticate or request access
  }
}
```

### ConfigurationError

Thrown when the SDK is misconfigured or a method is called with invalid options (for example, calling `addEmail` for a user who already has an email).

```typescript
try {
  await openfort.auth.addEmail({ email, callbackURL })
} catch (error) {
  if (error instanceof ConfigurationError) {
    console.log('Configuration error:', error.message)
    // Check SDK configuration
  }
}
```

### OAuthError

Thrown when OAuth authentication fails (for example, the provider is not configured, or the social account is already linked to another user).

```typescript
try {
  await openfort.auth.initOAuth({ provider, redirectTo })
} catch (error) {
  if (error instanceof OAuthError) {
    console.log('OAuth error:', error.message)
    // Handle OAuth-specific error
  }
}
```

### OTPError

Thrown when OTP (one-time password) operations fail.

```typescript
try {
  await openfort.auth.logInWithEmailOtp({ email, otp })
} catch (error) {
  if (error instanceof OTPError) {
    console.log('OTP error:', error.message)
    // Show OTP-specific error (expired, invalid, etc.)
  }
}
```

### RecoveryError

Thrown when wallet recovery operations fail.

```typescript
try {
  await openfort.embeddedWallet.recover({
    account: accountId,
    recoveryParams: { recoveryMethod: RecoveryMethod.PASSWORD, password: '...' },
  })
} catch (error) {
  if (error instanceof RecoveryError) {
    console.log('Recovery failed:', error.message)
    // Handle recovery-specific error
  }
}
```

### RequestError

Thrown when a request fails with an unexpected, non-HTTP error. API failures that don't map to a more specific class (including network errors and server errors) are thrown as a base `OpenfortError` with `error` set to `REQUEST_ERROR`, or to the code the API returned; check `statusCode` for the HTTP status.

```typescript
try {
  await openfort.embeddedWallet.list()
} catch (error) {
  if (error instanceof RequestError) {
    console.log('Request failed:', error.message)
  } else if (error instanceof OpenfortError && error.error === OPENFORT_ERROR_CODES.REQUEST_ERROR) {
    console.log('API request failed:', error.statusCode, error.message)
    // Handle network or server error
  }
}
```

### SessionError

Thrown when session operations fail (not logged in, session expired).

```typescript
try {
  await openfort.user.get()
} catch (error) {
  if (error instanceof SessionError) {
    console.log('Session error:', error.message)
    // Redirect to login
  }
}
```

### SignerError

Thrown when signer operations fail (signing, wallet not configured).

```typescript
try {
  await openfort.embeddedWallet.signMessage('Hello')
} catch (error) {
  if (error instanceof SignerError) {
    console.log('Signer error:', error.message)
    // Configure wallet first
  }
}
```

### UserError

Thrown when user operations fail (user not found, invalid user data).

```typescript
try {
  await openfort.auth.signUpWithEmailPassword({ email, password })
} catch (error) {
  if (error instanceof UserError) {
    console.log('User error:', error.message)
    // Handle user-specific error
  }
}
```

### Embedded Wallet Error Classes

The SDK also exports additional error classes thrown during embedded wallet operations:

```typescript
import {
  IframeConnectionDestroyedError,
  IframeHandshakeTimeoutError,
  IframeRpcTimeoutError,
  IframeSignEmptyResponseError,
  IframeSignTimeoutError,
  MissingProjectEntropyError,
  MissingRecoveryPasswordError,
  NotConfiguredError,
  OTPRequiredError,
  SessionEndedBeforeSetupError,
  WrongPasskeyError,
  WrongRecoveryPasswordError,
} from '@openfort/openfort-js'
```

| Error Class | When Thrown |
|-------------|------------|
| `IframeConnectionDestroyedError` | The embedded wallet iframe connection was closed while a call was in flight (for example, on logout) |
| `IframeHandshakeTimeoutError` | The embedded wallet iframe did not complete its connection handshake in time (unreachable, or blocked by CSP or the network) |
| `IframeRpcTimeoutError` | The embedded wallet iframe did not respond to a call in time |
| `IframeSignEmptyResponseError` | The embedded wallet iframe returned an empty signature |
| `IframeSignTimeoutError` | The embedded wallet iframe did not respond to a signing request in time (for example, a dismissed passkey prompt) |
| `MissingProjectEntropyError` | Shield encryption share is missing or not configured |
| `MissingRecoveryPasswordError` | Password recovery requires a password but none was provided |
| `NotConfiguredError` | Embedded wallet method called before `configure()` |
| `OTPRequiredError` | Operation requires OTP verification before proceeding |
| `SessionEndedBeforeSetupError` | The wallet session was torn down (for example, a component unmounted) before setup completed |
| `WrongPasskeyError` | Passkey authentication failed (wrong credential) |
| `WrongRecoveryPasswordError` | Incorrect recovery password provided |

### Passkey Error Classes

The SDK exports passkey-specific error classes for handling WebAuthn operations:

```typescript
import {
  PasskeyUserCancelledError,
  PasskeyCreationFailedError,
  PasskeyPRFNotSupportedError,
  PasskeyAssertionFailedError,
  PasskeySeedInvalidError,
  PASSKEY_ERROR_CODES,
} from '@openfort/openfort-js'
```

| Error Class | When Thrown |
|-------------|------------|
| `PasskeyUserCancelledError` | User cancelled the passkey operation (expected flow, not a failure) |
| `PasskeyCreationFailedError` | Passkey creation failed unexpectedly |
| `PasskeyPRFNotSupportedError` | Device does not support PRF extension for passkeys |
| `PasskeyAssertionFailedError` | Passkey assertion (authentication) failed |
| `PasskeySeedInvalidError` | Passkey seed is invalid or corrupted |

```typescript
try {
  await openfort.embeddedWallet.configure({
    recoveryParams: { recoveryMethod: RecoveryMethod.PASSKEY },
  })
} catch (error) {
  if (error instanceof PasskeyUserCancelledError) {
    console.log('User cancelled — this is expected, not an error')
  } else if (error instanceof PasskeyPRFNotSupportedError) {
    console.log('This device does not support passkey recovery')
  }
}
```

## Error Codes

The SDK exports error code constants for programmatic error handling:

```typescript
import {
  OPENFORT_ERROR_CODES,
  OPENFORT_AUTH_ERROR_CODES,
} from '@openfort/openfort-js'
```

### Authentication Error Codes

The SDK exports 40+ error codes. Key codes organized by category:

```typescript
const OPENFORT_AUTH_ERROR_CODES = {
  // Session & auth state
  ALREADY_LOGGED_IN: 'ALREADY_LOGGED_IN',
  NOT_LOGGED_IN: 'NOT_LOGGED_IN',
  SESSION_EXPIRED: 'SESSION_EXPIRED',
  INVALID_TOKEN: 'INVALID_TOKEN',

  // Credentials
  INVALID_CREDENTIALS: 'INVALID_EMAIL_OR_PASSWORD',
  PASSWORD_TOO_SHORT: 'PASSWORD_TOO_SHORT',
  PASSWORD_TOO_LONG: 'PASSWORD_TOO_LONG',

  // User management
  USER_ALREADY_EXISTS: 'USER_ALREADY_EXISTS',
  USER_NOT_FOUND: 'USER_NOT_FOUND',
  EMAIL_NOT_VERIFIED: 'EMAIL_NOT_VERIFIED',

  // OTP
  OTP_INVALID: 'INVALID_OTP',
  OTP_EXPIRED: 'OTP_EXPIRED',
  OTP_SEND_FAILED: 'OTP_SEND_FAILED',

  // Wallet & signer
  MISSING_SIGNER: 'MISSING_SIGNER',
  WRONG_RECOVERY_PASSWORD: 'WRONG_RECOVERY_PASSWORD',
  INCORRECT_PASSKEY: 'INCORRECT_PASSKEY',
  MISSING_PROJECT_ENTROPY: 'MISSING_PROJECT_ENTROPY',
  MISSING_USER_ENTROPY: 'MISSING_USER_ENTROPY',

  // General
  OPERATION_NOT_SUPPORTED: 'OPERATION_NOT_SUPPORTED',
  REQUEST_ERROR: 'REQUEST_ERROR',
  // ... and more
}
```

:::info
For the complete and up-to-date list of error codes, refer to the [SDK source code](https://github.com/openfort-xyz/openfort-js) or use your IDE's autocompletion on `OPENFORT_AUTH_ERROR_CODES`.
:::

## Best Practices

### 1. Use `instanceof` for Type Checking

Always use `instanceof` to check error types:

```typescript
try {
  await someOpenfortOperation()
} catch (error) {
  if (error instanceof AuthenticationError) {
    // Handle authentication error
  } else if (error instanceof ConfigurationError) {
    // Handle configuration error
  } else if (error instanceof OpenfortError) {
    // Handle any other Openfort error
  } else {
    // Handle unexpected errors
    throw error
  }
}
```

### 2. Handle Errors Gracefully

Provide user-friendly messages:

```typescript
const getErrorMessage = (error: unknown): string => {
  if (error instanceof AuthenticationError) {
    return 'Invalid email or password. Please try again.'
  }
  if (error instanceof SessionError) {
    return 'Your session has expired. Please log in again.'
  }
  if (error instanceof OTPError) {
    return 'Invalid or expired code. Please request a new one.'
  }
  if (error instanceof OpenfortError) {
    return 'An error occurred. Please try again.'
  }
  return 'An unexpected error occurred.'
}
```
