Skip to content

Report YAML syntax errors as located Q-1-1 (quarto-yaml 0.4.0) - #805

Merged
cscheid merged 5 commits into
mainfrom
bugfix/bd-x30aq7ae-frontmatter-yaml-error-code
Oct 8, 2026
Merged

cscheid merged 5 commits into
mainfrom
bugfix/bd-x30aq7ae-frontmatter-yaml-error-code

Conversation

@cscheid

@cscheid cscheid commented Oct 8, 2026

Copy link
Copy Markdown
Member

Fixes bd-x30aq7ae: a malformed YAML front-matter block was reported as Q-0-99 with an internal source path in the title ((at crates/pampa/src/utils/diagnostic_collector.rs:45)) and a span over the whole block. It now reports as Q-1-1 "YAML Syntax Error", located at the character where parsing failed.

Error: [Q-1-1] YAML Syntax Error
   ╭─[ bad-frontmatter.qmd:4:7 ]
 4 │ format: html
   │       ┬
   │       ╰── illegal placement of ':' indicator
ℹ The YAML front matter at the top of this document could not be parsed

The precise position comes from quarto-yaml 0.4.0 (posit-dev/quarto-yaml#21, upstream strand qy-scan-error-location-f9r4yvxq). Scan errors now carry location, and the message no longer embeds position text. Plan: claude-notes/plans/2026-10-08-frontmatter-yaml-error-code.md.

What changed

  • Dependency: quarto-yaml 0.3.0 → 0.4.0.
  • New pampa::utils::yaml_syntax_error: shared helpers that turn a quarto_yaml::Error into either a Q-1-1 diagnostic builder or prose ending in (line L, column C). It also contains the end-of-input clamp described below.
  • Frontmatter (pampa/src/pandoc/meta.rs): emits a located Q-1-1 diagnostic with a hint naming the front matter.
  • The bump regressed every site that stringified the error, so this PR fixes them all. Before 0.4.0, the message for parse_file callers ended in … at byte N line L column C, and that line number was file-relative and correct. After the bump, these sites would have printed no position at all:
    • Located Q-1-1 via QuartoError::Parse, with the file content registered under quarto-yaml's FileId (config_sources::yaml_parse_error): _quarto.yml, profile overlays and _quarto.yml.local, _metadata.yml.
    • Prose via describe_yaml_error: extension manifests (shown inside a Q-16-1 warning), the _variables.yml warning, language term files (×2), and the quarto use config loader.
    • No change needed: the Jupyter cell-option paths already used CellOptionsError::location(). They gain precise spans automatically.
  • End-of-input clamp. The scanner reports a missing closer ([a, b with no ]) at end of input, which is past the trailing newline. That put the caret on the closing --- of front matter, or on a code cell's first code line. Such locations are now pulled back to the end of the YAML's last content: title: [unclosed points at 2:17.

Regression report: changed tests

Every existing test whose assertions changed:

Test Before After Why
quarto::preview_static_e2e::a_failing_rerender_reports_diagnostics_and_does_not_reload asserted SSE text and stderr contain Q-0-99 asserts Q-1-1 (2 asserts) It pinned the bug: broken front matter was Q-0-99.
quarto::preview_static_e2e::boot_with_a_failing_page_still_serves_the_rest stderr contains Q-0-99 stderr contains Q-1-1 Same fixture, same reason.
quarto render_once_tests::page_error_is_reported_not_fatal diagnostics text contains Q-0-99 contains Q-1-1 Same.
quarto-core::pandoc_request_books::a_chapter_with_broken_front_matter_fails_before_any_chapter_renders out.error.to_lowercase().contains("front") out.error == "YAML Syntax Error", and the chapter's Q-1-1 diagnostic has a hint containing "front matter" Worth a look. PandocRequestOutcome.error is the title of the first error. The old title was "Failed to parse YAML frontmatter: …"; the new one is the catalog title, so the one-line summary no longer says "front matter". The context moved into the diagnostic's hint, which this test now asserts. This was a design decision (catalog title + hint); if hub-client surfaces only error, a custom title may be preferable.
quarto-core project::…::test_directory_metadata_invalid_yaml_fails to_string() contains "metadata"/"parse"/"yaml" is QuartoError::Parse with one Q-1-1 diagnostic, and the render contains _metadata.yml:1: Tightened to the new structured shape.
quarto-core::project_profile_overlays::overlay_yaml_parse_error_aborts_discovery result.is_err() also asserts a Q-1-1 located in _quarto-prod.yml with that file's content registered Strengthened; the input is unchanged.

Unchanged on purpose: ipynb_content_processor::cell_option_yaml_error_lands_in_owning_cell failed after the bump alone. The caret had moved to row 1 (print(1)), off the #| error: [unclosed option line. The end-of-input clamp fixes this, and the test passes unmodified. pampa::test_warnings still pins Q-0-99 for the caption-without-table fallback, which is out of scope (see follow-ups).

New tests

  • pampa::test_frontmatter_yaml_syntax_error: Q-1-1 with no internal path, the exact offending byte, non-ASCII text before the error, and an end-of-input error staying in bounds.
  • pampa utils::yaml_syntax_error::tests: location and fallback, describe_yaml_error, the end-of-input clamp, and line_column on char boundaries.
  • project_profile_overlays::base_config_yaml_syntax_error_is_located_q_1_1: _quarto.yml:3:6.
  • One position test per prose site: extension manifest, term file, _variables.yml warning, and quarto use.

Not covered by a test

  • The "before" strings for the config sites above come from reading quarto-yaml 0.3.0's Display (Parse error: {ScanError}, which ends in at byte N line L column C). They were not captured from a pre-change binary. The front-matter "before" was captured: claude-notes/plans/frontmatter-yaml-error-code-investigation/.

Verification

  • cargo xtask verify --skip-css-lint:
    • Rust tests: 16,007 / 16,008 pass. The one failure is smoke_all, whose failing cases all fail for local engine reasons: R/knitr "R process failed", and great_tables/pandas missing for Jupyter. The same documents fail on unmodified main in this environment.
    • Steps 6–14, including the hub-client WASM build and test:wasm: all pass.
  • --skip-css-lint is needed because main is red on lint:css. npm run lint:css -w hub-client also selects the nested hub-client/vscode-sync-experiment workspace. This is unrelated to this PR and tracked in bd-verify-css-lint-nested-ws-r0dd5vdk.

Follow-ups filed

  • bd-caption-warning-q099-5krqlz6w: "Caption found without a preceding table" fallback is still Q-0-99 with a path in the title.
  • bd-depth-limit-q099-f1q9vqjw: "too deeply nested" is Q-0-99 with no location.
  • bd-metadata-yml-error-swallowed-b8sjkxek: a malformed _metadata.yml is silently ignored (metadata_merge.rs calls .unwrap_or_default()). This predates this PR. The error is now structured, but it still never reaches the user.

🤖 Generated with Claude Code

cscheid and others added 5 commits October 8, 2026 09:54
…eak; span lost in quarto-yaml

Plan skeleton + repro. The precise position is dropped upstream
(quarto-yaml From<ScanError> sets location: None); code/title are
fixable in pampa. Audit lists the other user-reachable Q-0-99 sites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…yvxq)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (bd-x30aq7ae)

Malformed frontmatter surfaced as Q-0-99 with an internal source path in
the title and a whole-block span. quarto-yaml 0.4.0 now locates scan
errors (qy-scan-error-location-f9r4yvxq); frontmatter emits Q-1-1
'YAML Syntax Error' at the offending character.

0.4.0 also drops the position text from the error message, which every
site that stringified quarto_yaml::Error relied on. Those now go
through shared helpers so no position is lost:
- _quarto.yml, profile overlays/_quarto.yml.local, _metadata.yml:
  located Q-1-1 via QuartoError::Parse (config_sources::yaml_parse_error)
- extension manifests, _variables.yml, language term files, quarto use:
  '<message> (line L, column C)' (describe_yaml_error)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…0-99 tests (bd-x30aq7ae)

The scanner reports a missing closer at end of input, past the trailing
newline, which put the caret on the closing --- of front matter or on a
cell's first code line. Clamp such locations to the end of the YAML's
last content.

Tests that pinned the old behavior now expect Q-1-1: preview_static_e2e
(3 asserts), render_once page_error_is_reported_not_fatal, and the book
broken-front-matter test (its summary is now the catalog title; the
front-matter context is asserted via the chapter diagnostic's hint).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…x30aq7ae)

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

posit-snyk-bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

✅ 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 aaf01be into main Oct 8, 2026
11 checks passed
@cscheid
cscheid deleted the bugfix/bd-x30aq7ae-frontmatter-yaml-error-code branch October 8, 2026 19:46
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