rust-lang/mdBook · error

Duplicate file in SUMMARY.md: {:?}

Error message

Duplicate file in SUMMARY.md: {:?}

What it means

While parsing SUMMARY.md, mdBook tracks every link's source file location in a set; check_for_duplicates fails the build if the same source file is referenced by more than one SUMMARY item. Each chapter source file may appear only once in the table of contents.

Source

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

        Ok(Summary {
            title,
            prefix_chapters,
            numbered_chapters,
            suffix_chapters,
        })
    }

    /// Recursively check for duplicate files in the summary items.
    fn check_for_duplicates<'b>(
        items: &'b [SummaryItem],
        files: &mut HashSet<&'b PathBuf>,
    ) -> Result<()> {
        for item in items {
            if let SummaryItem::Link(link) = item {
                if let Some(location) = &link.location {
                    if !files.insert(location) {
                        bail!(anyhow::anyhow!(
                            "Duplicate file in SUMMARY.md: {:?}",
                            location
                        ));
                    }
                }
                // Recursively check nested items
                Self::check_for_duplicates(&link.nested_items, files)?;
            }
        }
        Ok(())
    }

    /// Parse the affix chapters.
    fn parse_affix(&mut self, is_prefix: bool) -> Result<Vec<SummaryItem>> {
        let mut items = Vec::new();
        debug!(
            "Parsing {} items",
            if is_prefix { "prefix" } else { "suffix" }

View on GitHub (pinned to dc21064fc2)

Solutions

  1. Remove or rename the duplicate entry in SUMMARY.md so each .md file appears once.
  2. Create a new .md file for the second entry and link to that instead.
  3. Use a draft chapter (empty link) as a placeholder if you only need a heading without a file.

Example fix

<!-- before: SUMMARY.md -->
- [Intro](intro.md)
- [Intro again](intro.md)

<!-- after -->
- [Intro](intro.md)
- [Overview](overview.md)
Defensive patterns

Strategy: validation

Validate before calling

// Lint SUMMARY.md for duplicate links before building
const links = summary.match(/\]\(([^)#]+)\)/g).map(s => s.slice(2, -1));
const dupes = links.filter((l, i) => links.indexOf(l) !== i);
if (dupes.length) throw new Error(`Duplicate files: ${dupes}`);

Prevention

When it happens

Trigger: Two or more Link items in SUMMARY.md (including nested/draft-part structures) point to the same .md file via their location; check_for_duplicates runs after parsing and raises this error on the second insertion.

Common situations: Copy-pasting a chapter line to create a second TOC entry; listing the same file as both a parent and a nested child; merging SUMMARY.md branches that both include one file.

Related errors


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