Skip to content
Handle Error for an Invalid PDF File
Error message when the viewer fails to load an invalid PDF file

When the React PDF viewer tries to open a PDF that is not valid (corrupt file, wrong format, or truncated data), React PDF Kit surfaces the failure through onLoadError on RPProvider. You can use that hook point to:

  1. Detect that the document failed to load
  2. Show a message or modal so users understand the file is invalid
  3. Offer a way to select another PDF file using useOpenFileContext so a child of RPProvider can call openFile() and use the built-in file dialog

After the user picks a valid PDF, the viewer loads normally and you can hide the error validation.

Use the src prop from RPProvider to load a PDF file. To handle load failures or clear error state, use onLoadError and onLoaded props respectively.

NameObjective
srcHandle a PDF file from different sources such as URL or Blob
onLoadErrorRun when the PDF fails to load and update the UI state (e.g. show modal)
onLoadedRun when the PDF loads successfully; clear error state

To retry with a local file after an error, keep src in React state and use the useOpenFileContext to update the document.

NameObjective
openFileUpdate the document without wiring your own <input type="file">
import { useState, type CSSProperties } from "react";
import {
RPConfig,
RPProvider,
RPLayout,
RPPages,
useOpenFileContext,
} from "@react-pdf-kit/viewer";
// Replace with an invalid URL while testing if you need to reproduce the error UI.
const SAMPLE_PDF_SRC =
"https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf";
const overlayStyle: CSSProperties = {
position: "fixed",
inset: 0,
// Above the viewer chrome so the dialog fully covers the app.
zIndex: 2147483647,
display: "grid",
placeItems: "center",
background: "rgba(0, 0, 0, 0.45)",
padding: 16,
pointerEvents: "auto",
};
const dialogStyle: CSSProperties = {
maxWidth: 400,
width: "100%",
padding: 24,
borderRadius: 8,
background: "#fff",
color: "#111827",
boxShadow: "0 25px 50px rgba(0, 0, 0, 0.25)",
};
const primaryButtonStyle: CSSProperties = {
marginTop: 12,
padding: "10px 16px",
borderRadius: 8,
border: "none",
background: "#2563eb",
color: "#fff",
fontSize: 14,
fontWeight: 600,
cursor: "pointer",
width: "100%",
};
type InvalidPdfErrorOverlayProps = {
message: string;
};
// useOpenFileContext only works under RPProvider, so this stays inside RPProvider below.
function InvalidPdfErrorOverlay({ message }: InvalidPdfErrorOverlayProps) {
const { openFile } = useOpenFileContext();
return (
<div
style={overlayStyle}
role="alertdialog"
aria-modal="true"
aria-labelledby="invalid-pdf-title"
>
<div style={dialogStyle}>
<h2 id="invalid-pdf-title" style={{ marginTop: 0 }}>
{message}
</h2>
<p style={{ marginTop: 16, marginBottom: 0, fontSize: 14 }}>
Pick a different PDF file.
</p>
{/* Same file dialog as the built-in open-file tool; updates the loaded PDF. */}
<button type="button" style={primaryButtonStyle} onClick={openFile}>
Choose PDF file…
</button>
</div>
</div>
);
}
export function AppPdfViewer() {
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const handleLoadError = (err: unknown) => {
const fallback = "Could not load this PDF.";
setErrorMessage(err instanceof Error ? err.message : fallback);
};
const handleLoaded = () => {
// Successful load (including after the user picks another file) clears the error UI.
setErrorMessage(null);
};
return (
<div style={{ position: "relative" }}>
<RPConfig licenseKey="YOUR_DOMAIN_TOKEN">
<RPProvider
src={SAMPLE_PDF_SRC}
onLoadError={handleLoadError}
onLoaded={handleLoaded}
>
{errorMessage ? (
<InvalidPdfErrorOverlay message={errorMessage} />
) : null}
<RPLayout toolbar>
<RPPages />
</RPLayout>
</RPProvider>
</RPConfig>
</div>
);
}