Skip to content

fix(render): exit non-zero on error diagnostics from successful renders#364

Merged
cscheid merged 1 commit into
mainfrom
bugfix/bd-zcjtaz78-error-diagnostics-exit-code
Jul 3, 2026
Merged

fix(render): exit non-zero on error diagnostics from successful renders#364
cscheid merged 1 commit into
mainfrom
bugfix/bd-zcjtaz78-error-diagnostics-exit-code

Conversation

@cscheid

@cscheid cscheid commented Jul 2, 2026

Copy link
Copy Markdown
Member

Braid strand: bd-zcjtaz78 (discovered during #362 / bd-yjs54ptg).

Problem

A render can complete successfully — output file written, no Pass-1/Pass-2 failure — while carrying a DiagnosticKind::Error diagnostic. Examples: a duplicate crossref identifier (Q-15-1, reported and skipped by the indexer), an include-file parse error (Q-5-3), or a Lua filter calling quarto.error(). Such a render printed Error: ... and tallied 1 error in the summary line, yet exited 0 — so CI reported success on output the user was explicitly told is broken.

Fix

should_exit_nonzero now reads ProjectRenderSummary::diagnostic_counts(), which aggregates every diagnostic source — pass-1/pass-2 failure diagnostics, project-level diagnostics, and per-document diagnostics on successful outputs (the previously-ignored source). Any error-severity diagnostic forces exit 1, with or without --strict. Warnings keep their existing semantics (exit 0 unless --strict); Info/Note never gate. The render still completes and writes its output; only the exit code changes.

The gate is now generic over OutputDiagnostics, which makes the per-output case directly unit-testable. Only crates/quarto is touched.

Behavior change for non-strict users, by design: CI pipelines that currently pass despite Error: output will start failing — the exit code now agrees with what the diagnostics already said.

Testing

  • TDD: 3 CLI integration tests (crates/quarto/tests/integration/render_exit_codes.rs) spawning the real q2 binary against a duplicate-table-id fixture; confirmed failing first (observed 1 error with exit 0).

  • 3 new unit tests for the gate's per-output arm (error / warning / info).

  • cargo nextest run --workspace: 9895 passed — no existing test relied on the old exit-0 behavior. cargo xtask verify --skip-hub-build and clippy green.

  • End-to-end, output inspected:

    $ q2 render duptbl.qmd     # two tables share {#tbl-dup}
    Error: [Q-15-1] Duplicate crossref identifier
    1 error
    # exit 1; duptbl.html still written
    

    Also verified a Lua filter's quarto.error() now yields exit 1, and a warnings-only document still exits 0.

🤖 Generated with Claude Code

…rs (bd-zcjtaz78)

A render that completes (output written, no pass failure) can still
carry an Error-kind diagnostic — e.g. a duplicate crossref id
(Q-15-1), reported and skipped by the indexer. Such a render printed
"Error: ..." and "1 error" yet exited 0, so CI reported success on
output the user was told is broken.

should_exit_nonzero now reads ProjectRenderSummary::diagnostic_counts,
which aggregates every diagnostic source including per-document
diagnostics on successful outputs: any error-severity diagnostic
forces exit 1, with or without --strict. Warnings keep the existing
behavior (exit 0 unless --strict). The render still completes; only
the exit code changes. The gate is now generic over OutputDiagnostics
so the per-output case is unit-testable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Jul 2, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@cscheid cscheid merged commit 64e459c into main Jul 3, 2026
8 checks passed
@cscheid cscheid deleted the bugfix/bd-zcjtaz78-error-diagnostics-exit-code branch July 3, 2026 16:04
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.

2 participants