getzola/zola · error
Found {} broken internal anchor link(s) {}
Error message
Found {} broken internal anchor link(s)
{} What it means
During load in check mode, Zola validates every internal link's #anchor against the target page's heading anchors. When internal_level is set to Error and any internal anchor links are broken (the anchor doesn't exist on the target page), load returns this error listing each bad link.
Source
Thrown at components/site/src/lib.rs:369
// Needs to be done after rendering markdown as we only get the anchors at that point
let internal_link_messages = link_checking::check_internal_links_with_anchors(self);
// log any broken internal links and error out if needed
if !internal_link_messages.is_empty() {
let messages: Vec<String> = internal_link_messages
.iter()
.enumerate()
.map(|(i, msg)| format!(" {}. {}", i + 1, msg))
.collect();
let msg = format!(
"Found {} broken internal anchor link(s)\n{}",
messages.len(),
messages.join("\n")
);
match self.config.link_checker.internal_level {
config::LinkCheckerLevel::Warn => log::warn!("{msg}"),
config::LinkCheckerLevel::Error => return Err(anyhow!(msg)),
}
}
// check external links, log the results, and error out if needed
if self.config.is_in_check_mode() && self.check_external_links {
let external_link_messages = link_checking::check_external_links(self);
if !external_link_messages.is_empty() {
let messages: Vec<String> = external_link_messages
.iter()
.enumerate()
.map(|(i, msg)| format!(" {}. {}", i + 1, msg))
.collect();
let msg = format!(
"Found {} broken external link(s)\n{}",
messages.len(),
messages.join("\n")
);
match self.config.link_checker.external_level {View on GitHub (pinned to 61d3082821)
Solutions
- Fix or remove each listed broken anchor link in your markdown
- Re-run zola check until zero broken anchors are reported
- Temporarily set link_checker.internal_level = "warn" in config.toml if you only want warnings instead of a failing build
- Use exact heading text — anchors are slugified from headings, so renamed headings change the anchor
Example fix
// before (content.md) [details](@/guide.md#configuration) // after (heading in guide.md is "## Configuring the site") [details](@/guide.md#configuring-the-site)
Defensive patterns
Strategy: validation
Validate before calling
// Run zola check in CI before building: // zola check && zola build // Or keep anchors consistent: link only to headings whose slug you verify
Try / catch
// Treat broken-anchor reports as warnings by configuring: // [link_checker] // internal_level = "warn" // then inspect warnings in build output
Prevention
- Run `zola check` in CI on every PR
- Never rename/delete headings without grepping for '#'-links to them
- Link to stable section anchors rather than frequently edited headings
When it happens
Trigger: Calling zola check (or Site::load with check mode) where a markdown link like [x](@/page.md#missing-anchor) or [](...#anchor) references an anchor that does not exist in the rendered target page; internal_level = "error" in config link_checker.
Common situations: Renaming or deleting a heading in a target page that other pages link to with a #fragment; editing a heading without updating slugified anchors; typos in anchor names.
Related errors
- could not parse domain `{}` from link
- could not parse domain `{}` from link: `{}`
- Anchor `#{}` not found on page
- Found {} broken external link(s) {}
- Failed to convert bytes to string : {}
AI-assisted analysis of getzola/zola@61d3082821 (2026-09-03).
Data as JSON: /api/errors/35f7e32ddb099e8a.
Report an issue: GitHub.