Skip to main content

Rendering Diagnostics

When a payload contains a typo in a style property, an invalid value, a missing asset, or text no available font can render, the engine degrades gracefully and continues — the render succeeds, but the affected bit is gone. Invisible, unless someone is reading the server's log warnings.

The diagnostics opt-in surfaces every such event inside the rendered document itself. Same pattern the barcode encoder already uses for invalid payloads ([barcode error: …] placeholders inline) — extended to styles, assets, fonts and canvas commands.

Live example

A fixture with seven intentional failure cases — a style typo, an invalid value, an undefined style reference, a missing image, pasted text without font coverage, a malformed canvas command, and inline shortcode typos. Markers appear below each case; the appendix on the last page aggregates them.

How to enable

Add a diagnostics block at the document root:

{
"document": {
"diagnostics": {
"showInDocument": "appendix",
"minLevel": "warning"
},
"content": [ ... ]
}
}
PropertyTypeDefaultDescription
showInDocumentstring"off"How to surface diagnostics: off (silent-drop behavior, log warnings only), appendix (aggregated table at end of document), inline (marker paragraphs directly below the element that raised each issue), both (inline markers + appendix).
minLevelstring"warning"Lowest severity to include: info (benign normalizations like case-folding), warning (silent drops), error (hard failures the renderer caught and skipped).

The default off is genuinely free: no collection work happens and the render carries no diagnostics overhead. Opting in always produces complete diagnostics — nothing else needs to be configured.

What gets captured

Every content-affecting failure in the renderer flows through this surface automatically — no per-site instrumentation. Coverage includes:

  • Style typosfontSizr: 14 instead of fontSize. Captured as warning.
  • Invalid valuestextAlign: "sideways", strokeLinecap: "wedge", unparseable colors. Captured as warning.
  • References to undefined styles{ "p": "...", "style": "doesNotExist" }. Captured as warning.
  • Missing or unresolved assets — an image path that resolves to nothing (block, inline [image], or canvas), a font family file that fails to load. Captured as warning.
  • Text without font coverage — content in a language no available font can render (for example pasted text in a script outside the built-in coverage and any declared fonts). The message names the script and points to the document's fonts section.
  • Canvas command failures — malformed SVG path data, unknown barcode symbology, commands missing required values.
  • Inline shortcode values[font, X] naming an undeclared family, unparseable [fontcolor]/[mark] colors, invalid [fontsize]/[letterspacing]/[align] values. Captured as warning; the tag and the rejected value are named.

The collector dedupes each distinct failure: a style with a typo applied to 100 paragraphs — or one missing font hit by 50 text runs — produces ONE entry, not 100. Severity is escalated if the same source reports a stronger issue later, so the appendix reflects the worst case.

Appendix format

When showInDocument is appendix or both, the renderer appends a "Rendering Diagnostics" section at the end of the document with a table:

SeveritySourcePropertyMessage
WARNINGintentionalTypofontSizrUnrecognized style property 'fontSizr' on style 'intentionalTypo'.
WARNINGstyleThatDoesNotExistStyle 'styleThatDoesNotExist' is not defined in the document's styles section.
WARNING(engine)missing/thermal-plot.pngImage asset 'missing/thermal-plot.png' could not be resolved; the image was skipped.
WARNING(engine)OtherNo available font can render Other text — "Բարեւ աշխարհ…" will be missing from the output. Add a font that covers this script to the document's fonts section.

Severity is color-coded: warnings in dark goldenrod, errors in firebrick, info in slate gray.

Inline markers

When showInDocument is inline or both, a marker paragraph is emitted directly below the element that raised each issue — whether the issue came from a named style or from the engine (a missing image, uncovered text, a canvas command). Elements don't need a style for their failures to surface:

⚠ intentionalTypo: fontSizr — Unrecognized style property 'fontSizr' on style 'intentionalTypo'.

Each distinct failure is marked once (dedupe), in the natural flow position, so authors see WHERE the problem happened.

Severity levels

LevelWhen emittedExample
infoBenign normalization — case-folded enum value, deprecated alias resolved, optional section absent.textAlign: "CENTER" accepted and normalized to "center".
warningSilent drop — property dropped or content substituted with a fallback. Renderer continued.Unknown property, invalid value, unresolved asset, uncovered text.
errorHard failure the renderer caught. Element skipped, render continued.Required asset missing, malformed barcode payload.

The default minLevel is warning so info-level normalizations stay quiet unless explicitly enabled.

Nothing else changes

Enabling diagnostics only adds the markers and the appendix — the rest of the render is identical, and server-side logging continues exactly as before. It is an additional surface for authors, not a replacement for operational logging.

  • Authoring environments — IDE / sandbox renders where authors should see their typos.
  • Pre-production validation — CI render of every template with showInDocument: "appendix" and a non-empty appendix flagged as a CI failure.
  • Customer-portal previews — let template authors debug their own definitions without log-diving.
  • Production renders for end-customers — the appendix is an authoring affordance, not customer-facing content. Default off is the right setting for delivered documents.

Format parity

Both PDF and DOCX render the same diagnostics shape with the same inline-marker and appendix behavior, and the markers and appendix are composed through each format's regular content pipeline — so their styling matches body content in both outputs.