Errors & debugging
The error taxonomy, template attribution on failure, and the diagnostics the development preview surfaces.
Render failures are typed and attributed. Every error surfaced from a template's
render() is a NuxtPdfError carrying a machine-readable code and the
templateKey. Development renders also carry templateFile and prefix the
message with the source path; production deliberately omits that preview-only
source attribution.
The error taxonomy
| Code | Meaning |
|---|---|
PDF_TEMPLATE_NOT_FOUND | No template matches the requested name |
PDF_TEMPLATE_INVALID | The template misuses the API. For example, it calls usePdfPageNumbers() outside a PDF render. |
PDF_TREE_INVALID | Invalid root/nesting, SVG references, or props outside a primitive's closed runtime surface |
PDF_LAYOUT_ERROR | The layout engine rejected the tree. This error includes font resolution failures ("Font family not registered"). |
PDF_LIMIT_EXCEEDED | The multi-pass loop did not converge within maxPasses |
PDF_ASSET_INVALID | A local asset failed extension, signature, size, or containment validation |
PDF_ASSET_BLOCKED | A remote asset was refused by the allowlist, timed out, exceeded its cap, or was otherwise blocked |
PDF_RENDER_ERROR | A render failure that does not fall into a more specific category |
Font-resolution failures deliberately surface as a single PDF_LAYOUT_ERROR
(font resolution is a layout sub-stage) and preserve React PDF's exact
"Font family not registered" text.
Template attribution
NuxtPdfError is thrown with the failing template's identity attached, so you
can log or branch on it precisely:
import { NuxtPdfError, pdf } from '#pdf'
export default defineEventHandler(async () => {
try {
const result = await pdf.report.render(props)
return result.response()
}
catch (error) {
if (error instanceof NuxtPdfError) {
console.error(error.code, error.templateKey, error.templateFile)
}
throw error
}
})The message itself is always prefixed with the template name. In development it
also includes the source file in pdfs/, so an unhandled preview error points
straight to the authoring file. Invalid nesting, unknown or misplaced props,
DOM/event attributes, and invalid SVG references fail with PDF_TREE_INVALID;
Nuxt PDF does not return a partially pruned document or silently forward
unsupported input to the engine.
Production render diagnostics
Every successful PdfRenderResult exposes frozen metadata for that completed
render. Its title and language reflect the PDF Info fields; filename is
response/download metadata and is not embedded as PDF Info. The result also
exposes the same immutable diagnostics object shown by the preview: duration,
byte length, page count, layout passes, and registered font faces. Diagnostics
contain no document content, props, or resource URLs, so an application can
forward them to its own metrics layer.
The development preview as a debugger
/_pdf is where you live while building a document. Each viewer page:
- offers the
sampleDataand every named scenario as tabs that swap the embedded PDF (an unknown?scenario=404s with the available names); - calls the public template's
render(props)once and embeds that exact completed result. There is no preview-specific rendering path; - shows the result's same diagnostics object, including duration and output size, page count, and the number of layout passes; and
- replaces the document with a safe error panel that shows the code, template, and relative source attribution, and a content-free summary, with no stack, props, customer text, URL, or absolute path. If that scenario rendered successfully before, the previous PDF stays visible with an explicit stale marker.
The layout-pass count is a useful debugging signal: a plain document reports one
pass; a table of contents reports two; a count that climbs toward maxPasses
means the document is struggling to converge (see
Contents, links & bookmarks).
The preview fixture sidecar and its source paths exist only in development.
Production compilation omits sampleData and scenarios from the template
module itself, and an artifact test rejects their canary values or preview-only
API tokens anywhere in the emitted Nitro server bundle.
Common failures
#pdfis untyped or/_pdfreturns 404 right after you enable the module. restartnuxt devor runnuxt prepareso Nuxt writes the registry.PDF_LAYOUT_ERROR: Font family not registeredmeans that thefontFamilyin a style is not declared inpdf.fonts, or the face (weight/style) is missing.PDF_ASSET_INVALIDmeans that the image or font path escapes its root, has the wrong signature, or exceeds its size cap.PDF_LIMIT_EXCEEDEDmeans that the document's layout depends on the page numbers it prints, so it never converges; it is not made to converge (see the note on non-convergence in Contents, links & bookmarks).