rust-lang/mdBook · error

Unable to get last link because the list of SummaryItems doe

Error message

Unable to get last link because the list of SummaryItems doesn't contain any Links

What it means

get_last_link retrieves the final Link in a list of SummaryItems, needed to append a nested item under it while parsing nested numbered chapters. If the list contains no Link items (filtered via maybe_link_mut yields nothing), the iterator is empty and this error is returned instead of panicking.

Source

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

            if let Some(ref mut number) = link.number {
                number[level] += by;
            }

            update_section_numbers(&mut link.nested_items, level, by);
        }
    }
}

/// Gets a pointer to the last `Link` in a list of `SummaryItem`s, and its
/// index.
fn get_last_link(links: &mut [SummaryItem]) -> Result<(usize, &mut Link)> {
    links
        .iter_mut()
        .enumerate()
        .filter_map(|(i, item)| item.maybe_link_mut().map(|l| (i, l)))
        .next_back()
        .ok_or_else(|| {
            anyhow::anyhow!(
                "Unable to get last link because the list of SummaryItems \
                 doesn't contain any Links"
            )
        })
}

/// Removes the styling from a list of Markdown events and returns just the
/// plain text.
fn stringify_events(events: Vec<Event<'_>>) -> String {
    events
        .into_iter()
        .filter_map(|t| match t {
            Event::Text(text) | Event::Code(text) => Some(text.into_string()),
            Event::SoftBreak => Some(String::from(" ")),
            _ => None,
        })
        .collect()
}

View on GitHub (pinned to dc21064fc2)

Solutions

  1. Ensure each nested list in the numbered section is directly preceded by a chapter link (the parent).
  2. Remove or move any separator/spacer item that appears before the first link of a numbered section.
  3. Fix SUMMARY.md structure so nested items follow a valid parent link.

Example fix

<!-- before: SUMMARY.md -->
- ---
  - [Child](child.md)

<!-- after -->
- [Parent](parent.md)
  - [Child](child.md)
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every nested list has a preceding parent link
let prevWasLink = false;
for (const line of summary.split('\n')) {
  if (/^\s{2,}-\s\[/.test(line) && !prevWasLink) throw new Error('nested list without parent link');
  prevWasLink = /^-\s\[/.test(line);
}

Prevention

When it happens

Trigger: parse_nested_numbered encounters a nested list whose preceding items contain no Link — e.g. the numbered list starts with a Spacer or draft/separator item and then indents a nested list, so next_back() finds no link to attach the nested chapter to.

Common situations: Placing a separator line ("---") at the start of the numbered section and indenting the first chapter under it; malformed SUMMARY where a nested list appears before any parent link; script-generated SUMMARY emitting lists without parents.

Related errors


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