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.
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
- Anchor `# ` not found on page
- could not parse domain
- could not parse domain
- Found broken external link(s)
- Can't watch ` ` for changes in folder ` `. Does it exist…
AI-assisted analysis of getzola/zola@61d3082821 (2026-09-03).
Data as JSON: /api/errors/35f7e32ddb099e8a.
Report an issue: GitHub.
Appendix: 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)