rust-lang/mdBook · error

failed to parse SUMMARY.md line {}, column {}: {}

Error message

failed to parse SUMMARY.md line {}, column {}: {}

What it means

parse_error is the helper used by SUMMARY.md parsers to construct user-facing errors. It captures the parser's current (line, column) location via current_location and wraps the message with it, so users see exactly where in SUMMARY.md parsing failed.

Source

Thrown at crates/mdbook-summary/src/lib.rs:568

                    );

                    link.number = Some(number);

                    return Ok(SummaryItem::Link(link));
                }
                other => {
                    warn!("Expected a start of a link, actually got {:?}", other);
                    bail!(self.parse_error(
                        "The link items for nested chapters must only contain a hyperlink"
                    ));
                }
            }
        }
    }

    fn parse_error<D: Display>(&self, msg: D) -> Error {
        let (line, col) = self.current_location();
        anyhow::anyhow!(
            "failed to parse SUMMARY.md line {}, column {}: {}",
            line,
            col,
            msg
        )
    }

    /// Try to parse the title line.
    fn parse_title(&mut self) -> Option<String> {
        loop {
            match self.next_event() {
                Some(Event::Start(Tag::Heading {
                    level: HeadingLevel::H1,
                    ..
                })) => {
                    debug!("Found a h1 in the SUMMARY");

                    let tags = collect_events!(self.stream, end TagEnd::Heading(HeadingLevel::H1));

View on GitHub (pinned to dc21064fc2)

Solutions

  1. Open SUMMARY.md at the reported line/column and fix the syntax problem described after the location.
  2. Validate the overall structure: optional prefix chapters, one `# Summary` header, one numbered list, then suffix chapters.
  3. Regenerate a known-good SUMMARY.md (e.g. from a fresh `mdbook init`) and re-apply entries carefully.

Example fix

// before: SUMMARY.md line 3, column 5
- [Chapter 1](ch1.md]

// after
- [Chapter 1](ch1.md)
Defensive patterns

Strategy: try-catch

Try / catch

// Rust
match mdbook::build(&mut book) {
    Err(e) if e.to_string().starts_with("failed to parse SUMMARY.md") => {
        eprintln!("Fix SUMMARY.md at the reported line/column: {e}");
        std::process::exit(1);
    }
    Err(e) => return Err(e),
    Ok(()) => {},
}

Prevention

When it happens

Trigger: Any syntax problem in SUMMARY.md that triggers a bail!(self.parse_error(...)) path — malformed links, invalid nesting, bad affix structure, etc. The message shown embeds the line and column of the offending event.

Common situations: Hand-editing SUMMARY.md and introducing typos; unbalanced brackets or quotes in links; invalid UTF-8 or inconsistent indentation confusing the Markdown event stream; corrupted SUMMARY after a bad merge.

Understand the failure class

Related errors


AI-assisted analysis of rust-lang/mdBook@dc21064fc2 (2026-09-01). Data as JSON: /api/errors/aa15d780883ed60f. Report an issue: GitHub.