# Error states

Show a clear message with Retry when a document can't load or render, and receive a typed error for your own handling.

## Basics

When a document fails to load, the viewer shows an alert with a Retry button and keeps the toolbar usable.

**Demo: A missing file**

```tsx
import { PdfViewer } from '@kingtech/react-pdf-viewer';

export default function Demo() {
  return <PdfViewer source="/samples/does-not-exist.pdf" />;
}
```

The toolbar stays so that fullscreen can always be left. Aborted loads and canceled renders are never reported as errors.

### Failure types

Every failure reaches `onError` as a `PdfViewerError` with a machine-readable `code`, a readable `message`, the HTTP `status` where there is one, and the original `cause`.

**Demo: Each failure and its onError payload**

```tsx
import { PdfViewer, type PdfViewerError } from '@kingtech/react-pdf-viewer';
import { useState } from 'react';

const CASES = {
  'Missing file (404)': '/samples/does-not-exist.pdf',
  'Not a PDF': '/samples/not-a-pdf.pdf',
  'Password protected': '/samples/password.pdf',
  'Blocked by CORS': 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
};

type Case = keyof typeof CASES;

export default function Demo() {
  const [current, setCurrent] = useState<Case>('Missing file (404)');
  const [error, setError] = useState<PdfViewerError | null>(null);

  return (
    <>
      <p className="demo-controls">
        <label>
          Failure{' '}
          <select
            value={current}
            onChange={(event) => {
              setCurrent(event.target.value as Case);
              setError(null);
            }}
          >
            {Object.keys(CASES).map((name) => (
              <option key={name}>{name}</option>
            ))}
          </select>
        </label>
      </p>
      <PdfViewer key={current} source={CASES[current]} onError={setError} />
      <pre className="demo-output" aria-label="onError payload">
        {error
          ? JSON.stringify(
              { code: error.code, status: error.status, message: error.message },
              null,
              2,
            )
          : 'onError not called yet'}
      </pre>
    </>
  );
}
```

`RENDER_FAILED` replaces only the page that failed; the password codes are covered in [Password protection](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/password-protection/).

## Reporting errors

```tsx
<PdfViewer
  source={url}
  onError={(error) =>
    logger.warn('pdf-viewer', error.code, { status: error.status, cause: error.cause })
  }
/>
```

HTTP errors that `onHttpError` handles (for example a 401 that redirects to sign-in) are not reported; see [Authenticated requests](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/authenticated-requests/).

## Customization

`renderError(error, { retry })` replaces the error view for document and page errors.

**Demo: A custom error view**

```tsx
import { PdfViewer } from '@kingtech/react-pdf-viewer';

export default function Demo() {
  return (
    <PdfViewer
      source="/samples/does-not-exist.pdf"
      renderError={(error, { retry }) => (
        <div role="alert" style={{ padding: 24, border: '1px solid #fca5a5', borderRadius: 12 }}>
          <strong>We couldn’t open this document.</strong>
          <p>
            {error.code === 'HTTP_ERROR' && error.status === 404
              ? 'It may have been moved or deleted.'
              : error.message}
          </p>
          <button type="button" onClick={retry}>
            Try again
          </button>
        </div>
      )}
    />
  );
}
```

Colors of the default view are CSS variables (`--rpv-error-bg`, `--rpv-error-fg`, `--rpv-error-icon`); see the [customization guide](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/customization/).

## Advanced / escape hatch

`reload()` on the [imperative API](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/imperative-api/) retries from anywhere in your app. With [`usePdfDocument`](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/headless/), `error` and `reload` are returned directly.

## Limitations

- **Messages are in English by default.** `HTTP_ERROR` messages come from `getHttpErrorMessage`, which reads RFC 7807 bodies; other codes carry English messages. Workaround: map `error.code` to your own text in `renderError`.
- **CORS failures are indistinguishable from offline.** Browsers do not tell scripts why a cross-origin request failed, so both appear as `NETWORK_ERROR`. Workaround: explain both possibilities in your error view, as the demo above does.

## API

- [PdfViewerError](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/api/pdf-viewer-error.md)
- [PdfViewerErrorCode](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/api/pdf-viewer-error-code.md)

---

## PdfViewerError reference

A typed viewer error. Aborted loads and canceled renders are never reported as errors.

### Used by

- [Error states](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/error-states.md)

### Import

```ts
import type { PdfViewerError } from '@kingtech/react-pdf-viewer';
```

### Properties

| Name | Type | Default | Required | Description |
| --- | --- | --- | --- | --- |
| `code` | `PdfViewerErrorCode` | — | Yes | Machine-readable category. |
| `message` | `string` | — | Yes | Human-readable message; for `HTTP_ERROR` it comes from `getHttpErrorMessage`. |
| `status` | `number` | — | No | The HTTP status, for `HTTP_ERROR`. |
| `cause` | `unknown` | — | No | The underlying error, when there is one. |

### Source

[packages/react-pdf-viewer/src/types.ts](https://github.com/kiralygyula92/react-pdf-viewer/blob/main/packages/react-pdf-viewer/src/types.ts#L93)


---

## PdfViewerErrorCode reference

Machine-readable category of a `PdfViewerError`, for handling failures such as a missing password or an HTTP error in code.

### Used by

- [Error states](https://react-pdf-viewer-chi.vercel.app/react-pdf-viewer/error-states.md)

### Import

```ts
import type { PdfViewerErrorCode } from '@kingtech/react-pdf-viewer';
```

Signature: `type PdfViewerErrorCode = 'PDFJS_LOAD_FAILED' | 'NETWORK_ERROR' | 'HTTP_ERROR' | 'INVALID_PDF' | 'PASSWORD_REQUIRED' | 'INCORRECT_PASSWORD' | 'RENDER_FAILED' | 'DOWNLOAD_FAILED' | 'PRINT_FAILED' | 'UNKNOWN'`

### Properties

| Name | Type | Default | Required | Description |
| --- | --- | --- | --- | --- |
| `PDFJS_LOAD_FAILED` | `'PDFJS_LOAD_FAILED'` | — | No | The `pdfjs-dist` module or its worker failed to load. |
| `NETWORK_ERROR` | `'NETWORK_ERROR'` | — | No | `fetch` rejected: offline, CORS, DNS, … |
| `HTTP_ERROR` | `'HTTP_ERROR'` | — | No | The server answered with a non-2xx status (`status` is set). |
| `INVALID_PDF` | `'INVALID_PDF'` | — | No | The bytes are not a valid PDF. |
| `PASSWORD_REQUIRED` | `'PASSWORD_REQUIRED'` | — | No | The document is encrypted and no password was supplied. |
| `INCORRECT_PASSWORD` | `'INCORRECT_PASSWORD'` | — | No | The supplied password is wrong. |
| `RENDER_FAILED` | `'RENDER_FAILED'` | — | No | A page failed to render. |
| `DOWNLOAD_FAILED` | `'DOWNLOAD_FAILED'` | — | No | Saving the document failed. |
| `PRINT_FAILED` | `'PRINT_FAILED'` | — | No | Printing failed. |
| `UNKNOWN` | `'UNKNOWN'` | — | No | Anything else. |

### Source

[packages/react-pdf-viewer/src/types.ts](https://github.com/kiralygyula92/react-pdf-viewer/blob/main/packages/react-pdf-viewer/src/types.ts#L68)

