> For the complete documentation index, see [llms.txt](https://docs.humanity.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.humanity.org/build-with-humanity/build-with-the-sdk-api/humanity-org-react-sdk/error-handling.md).

# Error handling

The SDK provides typed error classes and utilities so you can handle failures precisely — whether it's an expired token, a blocked popup, or a failed verification.

## Error Types

All SDK errors are instances of `HumanityReactError`, which carries:

* **`message`** — human-readable description
* **`code`** — machine-readable error code (e.g. `'invalid_grant'`, `'token_expired'`, `'popup_blocked'`)
* **`status`** — HTTP status code when applicable

```tsx
import { isHumanityError, type HumanityReactError } from '@humanity-org/react-sdk';

function handleError(err: unknown) {
  if (isHumanityError(err)) {
    console.error('Humanity error:', {
      message: err.message,
      code: err.code,
      status: err.status,
    });
  }
}
```

## Global Error Handler

Use the `onError` prop on `HumanityProvider` to catch all auth and verification errors in one place — ideal for routing to an error reporting service:

```tsx
import { HumanityProvider } from '@humanity-org/react-sdk';
import * as Sentry from '@sentry/react';

<HumanityProvider
  clientId="hp_xxx"
  redirectUri="https://app.com/callback"
  onError={(error) => {
    Sentry.captureException(error, {
      extra: { code: error.code, status: error.status },
    });
  }}
>
  <App />
</HumanityProvider>
```

## Per-Component Error Callbacks

Each component that performs async operations (`HumanityConnect`, `HumanityVerify`) accepts an `onError` prop for local handling:

```tsx
<HumanityConnect
  scopes={['openid', 'profile']}
  onSuccess={(result) => handleLogin(result)}
  onError={(error) => {
    if (error.code === 'popup_blocked') {
      showToast('Please allow popups for this site.');
    } else {
      showToast('Login failed. Please try again.');
    }
  }}
/>
```

## Error Boundary

Wrap authentication-critical UI with `HumanityErrorBoundary` to catch unexpected render-time errors:

```tsx
import { HumanityErrorBoundary, HumanityConnect } from '@humanity-org/react-sdk';

<HumanityErrorBoundary
  fallback={(error) => (
    <div>
      <p>Authentication unavailable: {error.message}</p>
      <button onClick={() => window.location.reload()}>Retry</button>
    </div>
  )}
  onError={(error, info) => {
    console.error('Boundary caught:', error, info.componentStack);
  }}
>
  <HumanityConnect />
</HumanityErrorBoundary>
```

## Hook-Level Error State

Hooks expose an `error` field you can check directly:

```tsx
import { useAuth, useVerification } from '@humanity-org/react-sdk';

function AuthStatus() {
  const { error: authError } = useAuth();
  const { status, error: verifyError } = useVerification();

  if (authError) return <p>Auth error: {authError.message}</p>;
  if (status === 'error') return <p>Verification error: {verifyError?.message}</p>;

  return null;
}
```

## Error Utilities

| Export            | Description                                                         |
| ----------------- | ------------------------------------------------------------------- |
| `isHumanityError` | Type guard — returns `true` if the value is a `HumanityReactError`. |
| `createError`     | Factory for creating typed SDK errors.                              |
| `normalizeError`  | Converts any thrown value into a `HumanityReactError`.              |
| `parseOAuthError` | Parses OAuth error parameters from a callback URL.                  |

## Common Error Codes

| Code             | Cause                                               | Fix                                                   |
| ---------------- | --------------------------------------------------- | ----------------------------------------------------- |
| `popup_blocked`  | Browser blocked the OAuth popup                     | Prompt user to allow popups, or use `mode="redirect"` |
| `token_expired`  | Access token has expired                            | Call `refreshToken()` or prompt re-login              |
| `invalid_grant`  | Refresh token is invalid or revoked                 | Prompt re-login                                       |
| `access_denied`  | User declined the OAuth consent screen              | Show an informative message and retry option          |
| `network_error`  | Request failed due to connectivity                  | Retry after checking network                          |
| `scope_mismatch` | Requested scopes don't match registered application | Verify scopes in the Developer Portal                 |

## Production Checklist

Before going live, verify:

* [ ] `onError` global handler is configured and routes to your monitoring service
* [ ] `HumanityErrorBoundary` wraps authentication-critical UI
* [ ] `popup_blocked` case is handled (show instructions or fall back to redirect mode)
* [ ] Token expiry is handled gracefully (auto-refresh or re-login prompt)
* [ ] Redirect URI is registered for both sandbox and production environments
* [ ] `storage="memory"` is used, or you've explicitly accepted the XSS risk of `localStorage`


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.humanity.org/build-with-humanity/build-with-the-sdk-api/humanity-org-react-sdk/error-handling.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
