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.
- Output
- Template
- Data
How to enable
Add a diagnostics block at the document root:
{
"document": {
"diagnostics": {
"showInDocument": "appendix",
"minLevel": "warning"
},
"content": [ ... ]
}
}
| Property | Type | Default | Description |
|---|---|---|---|
showInDocument | string | "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). |
minLevel | string | "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 typos —
fontSizr: 14instead offontSize. Captured as warning. - Invalid values —
textAlign: "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
fontssection. - 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:
| Severity | Source | Property | Message |
|---|---|---|---|
| WARNING | intentionalTypo | fontSizr | Unrecognized style property 'fontSizr' on style 'intentionalTypo'. |
| WARNING | styleThatDoesNotExist | Style 'styleThatDoesNotExist' is not defined in the document's styles section. | |
| WARNING | (engine) | missing/thermal-plot.png | Image asset 'missing/thermal-plot.png' could not be resolved; the image was skipped. |
| WARNING | (engine) | Other | No 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
| Level | When emitted | Example |
|---|---|---|
info | Benign normalization — case-folded enum value, deprecated alias resolved, optional section absent. | textAlign: "CENTER" accepted and normalized to "center". |
warning | Silent drop — property dropped or content substituted with a fallback. Renderer continued. | Unknown property, invalid value, unresolved asset, uncovered text. |
error | Hard 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.
Recommended for
- 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.
NOT recommended for
- Production renders for end-customers — the appendix is an authoring affordance, not customer-facing content. Default
offis 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.