Skip to content

docs(errors): MissingBackendException is documented where it fires - #495

Merged
DemchaAV merged 1 commit into
developfrom
docs/missing-backend-throw-site
Aug 3, 2026
Merged

docs(errors): MissingBackendException is documented where it fires#495
DemchaAV merged 1 commit into
developfrom
docs/missing-backend-throw-site

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Why

On a lean graph-compose-core classpath the session never opens. create() resolves the font-metrics provider — layout measures text before anything is drawn — so the exception fires there and the stack trace points at the caller's create(), not at a render call. Reproduced by compiling a probe against core/target/classes with no backend jar: BackendProviders:204 → :200 → :136 → DocumentSession:1163 → :114 → GraphCompose:457, with the toPdfBytes() step never reached.

CHANGELOG.md records an earlier pass that put this right in core/README.md, render-pdf/README.md, the root README and the exception's Javadoc. It stopped at the repository root. Three documents under docs/ still sent the reader to buildPdf(), and docs/migration/v2.0.0-modules.md links straight into the troubleshooting entry, so the two reinforced each other.

What changed

  • docs/troubleshooting.md — the cause names create() and says why measurement is what needs the backend. Adds the one case that genuinely surfaces at the output call: buildPptx() when the PPTX backend is missing and the PDF one is present. The heading no longer says "when rendering"; its single inbound anchor, in the migration guide, moves with it. Also drops the version from "the lean 2.0 engine" — the artifact does not get renamed each minor.
  • docs/migration/v2.0.0-modules.md, docs/adr/0016-multi-module-packaging.md — same correction.
  • MissingBackendContractTest — one assertion wrapped create(), pageFlow(...) and toPdfBytes(), so only the first line ever ran while the test name promised the third. That name is the likely origin of the wording in all three documents. Split into openingASessionWithoutABackendThrowsNamingRenderPdf, plus configuringADocumentDoesNotNeedABackendUntilTheSessionOpens which pins the other side of the boundary — a builder that resolved eagerly, or one that deferred past create(), now fails.

Two adjacent defects of the same class — a document pointing the reader somewhere it is not:

  • docs/README.md described canonical-legacy-parity.md as a "canonical (v1.5+) vs legacy compatibility matrix". The document was rewritten for the 2.1 line and says the surface it was measured against was removed in 2.0; the index entry had not moved.
  • docs/recipes/extending.md — three of the four cross-references pointed at extension-guide.md headings that had since been renamed or renumbered, so the reader landed at the top of the page. One row was also mislabelled: "Add a render backend" linked at § 3, which is Add a render handler for an existing backend; the row it wanted is § 4. The missing handler row is added.

Verification

./mvnw -B -ntp clean verifyBUILD SUCCESS, exit 0, 692 tests in the closing module. MissingBackendContractTest 3 → 4.

Anchor sweep over every ](…#…) link in docs/: 59 checked, and the three fixed here no longer resolve to a missing heading. A repo-wide grep finds no remaining prose placing the exception at a render call.

Known limit

The same sweep flags 15 same-file table-of-contents anchors in four files this PR does not touch (roadmaps/migration-v1-5-to-v1-6.md, migration-v1-8-to-v1-9.md, templates/v2-layered/{authoring-presets,contributor-guide,using-templates}.md). Some are likely false positives — my checker does not reproduce GitHub's slug rules for em dashes — so I have not touched them blind. The existing link guard validates that the file exists, not the anchor; extending it and sweeping the results is worth its own change.

Lane: docs + test. No production code, no public API.

An earlier pass moved the module READMEs, the root README and the
exception's own Javadoc onto create(), and stopped at the repository root.
Three documents under docs/ kept telling a reader to look at buildPdf():
the troubleshooting entry, the 2.0 migration guide and ADR 0016 — and the
migration guide links straight into the troubleshooting entry, so the two
reinforced each other. On a lean core the session never opens: create()
resolves the font-metrics provider, because layout measures text before
anything is drawn, and the stack trace points at the caller's create().

All three now name that call. The troubleshooting entry adds the one case
that really does surface at the output call — buildPptx() when the PPTX
backend is missing and the PDF one is not — and its heading no longer says
"when rendering"; the single inbound anchor moves with it.

MissingBackendContractTest carried the same confusion: one assertion wrapped
create(), pageFlow(...) and toPdfBytes(), so only the first line ever ran
while the test name promised the third. It is split, and a second case pins
the other side of the boundary: configuring a document needs no backend,
opening the session does.

Also: the docs index described canonical-legacy-parity.md as a v1.5-era
legacy matrix, which the document itself stopped being; and three of the
four cross-references in the extension recipe pointed at extension-guide
headings that had been renamed or renumbered, landing the reader at the top
of the page.

./mvnw -B -ntp clean verify — BUILD SUCCESS, 692 tests in the closing
module. MissingBackendContractTest 3 -> 4.
@DemchaAV
DemchaAV force-pushed the docs/missing-backend-throw-site branch from 640faaa to 0e9fe93 Compare August 3, 2026 13:37
@DemchaAV

DemchaAV commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

Both points applied — the first one turned out to be a claim of mine that the code did not support.

buildPptx() now goes through the public API in a test. The class Javadoc said the render-time site "is what the two format-specific cases below cover", but those call BackendProviders.fixedLayout("pptx") directly — the resolver, not the path a caller takes to it. MissingPptxBackendContractTest lands in render-pdf, which is the only module whose classpath has one backend and not the other: measurement resolves, the session opens, and session.buildPptx(...) throws naming graph-compose-render-pptx. The run log confirms it went through the convenience path rather than the resolver — document.pptx.build.failed … errorType=MissingBackendException. The Javadoc now points at that test instead of overstating what the engine-side cases cover.

One ordering detail worth recording, since it would make the test pass for the wrong reason: a document with no roots fails ensureRenderable() with IllegalStateException before any backend lookup, so the pageFlow(...) line is load-bearing, not decoration. It is called out in the test's Javadoc.

Old anchor preserved. <a id="missingbackendexception-when-rendering"></a> sits above the renamed heading, so anything already published against the old fragment still lands on the entry.

./mvnw -B -ntp clean verifyBUILD SUCCESS, 692 tests in the closing module. MissingBackendContractTest 4, MissingPptxBackendContractTest 1.

Head is now 0e9fe937; CI re-running.

@DemchaAV
DemchaAV merged commit ccf0fed into develop Aug 3, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the docs/missing-backend-throw-site branch August 3, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant