{"record":{"id":"702b03ea08ace190","repo":"getzola/zola","slug":"anchor-not-found-on-page","errorCode":null,"errorMessage":"Anchor `#{}` not found on page","messagePattern":"Anchor `#(.+?)` not found on page","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"components/link_checker/src/lib.rs","lineNumber":117,"sourceCode":"\nfn has_anchor(url: &str) -> bool {\n    match url.find('#') {\n        Some(index) => match url.get(index..=index + 1) {\n            Some(\"#/\") | Some(\"#!\") | None => false,\n            Some(_) => true,\n        },\n        None => false,\n    }\n}\n\nfn check_page_for_anchor(url: &str, body: String) -> errors::Result<()> {\n    let index = url.find('#').unwrap();\n    let anchor = url.get(index + 1..).unwrap();\n\n    if has_anchor_id(&body, anchor) {\n        Ok(())\n    } else {\n        Err(anyhow!(\"Anchor `#{}` not found on page\", anchor))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{\n        LINKS, LinkChecker, check_page_for_anchor, check_url, has_anchor, is_valid, message,\n    };\n    use reqwest::StatusCode;\n\n    // NOTE: HTTP mock paths below are randomly generated to avoid name\n    // collisions. Mocks with the same path can sometimes bleed between tests\n    // and cause them to randomly pass/fail. Please make sure to use unique\n    // paths when adding or modifying tests that use Mockito.\n\n    #[test]\n    fn can_validate_ok_links() {\n        let mut server = mockito::Server::new();","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/components/link_checker/src/lib.rs#L99-L135","documentation":"The link checker, when validating in-page anchors, fetches the page body and searches for a matching id/name via `has_anchor_id`. If the fragment identifier after '#' is not found anywhere in the page, `check_page_for_anchor` returns this error, marking the internal link as broken.","triggerScenarios":"A markdown/HTML link like `[text](./page.md#section)` where page.md exists but no heading or element defines `id=\"section\"` (or a matching `name` attribute) — detected by `check_page_for_anchor`, invoked from `check_url`.","commonSituations":"Renaming or deleting a heading without updating links to its anchor; anchors with special characters that Zola slugifies differently (e.g. 'C++' -> 'c'); case mismatches; anchor pointing at a heading rendered by shortcodes not present at check time.","solutions":["Open the target page and find the actual rendered id of the section; update the link's fragment to match","Slugify the heading text the same way Zola does (lowercase, spaces to hyphens, punctuation stripped) and use that as the anchor","If the target truly should not have an anchor, remove the '#fragment' from the link","Add an explicit anchor/id to the target element"],"exampleFix":"// before\n[docs](./guide.md#Quick-Start)\n// after\n[docs](./guide.md#quick-start)","handlingStrategy":"validation","validationCode":"import fs from 'fs';\nfunction anchorsInFile(path) {\n  const html = fs.readFileSync(path, 'utf8');\n  return new Set([...html.matchAll(/(?:id|name)=\"([^\"]+)\"/g)].map((m) => m[1]));\n}\nfunction linkIsValid(pageAnchors, url) {\n  const i = url.indexOf('#');\n  if (i === -1) return true;\n  return pageAnchors.has(url.slice(i + 1));\n}","typeGuard":"function hasAnchor(html, fragment) {\n  return typeof fragment === 'string' &&\n    new RegExp(`(?:id|name)=[\"']${CSS.escape(fragment)}[\"']`).test(html);\n}","tryCatchPattern":"match check_internal_link(url) {\n    Ok(()) => {},\n    Err(e) if e.to_string().starts_with(\"Anchor `#\") => {\n        log::warn!(\"dead anchor, fix link: {} ({e})\", url);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Slugify heading text the same way the site generator does when hand-writing anchors","Run the link checker in CI and treat anchor failures as warnings to fix before merge","When renaming/deleting headings, grep the content directory for links to the old fragment","Prefer linking to the page without a fragment unless the section anchor is verified"],"tags":["link-checker","anchors","broken-link"],"backgroundTag":"broken-anchor-link","analyzedSha":"61d30828217957120309db657950224edf9707e2","analyzedAt":"2026-09-03T14:39:09.727Z","contentChangedAt":"2026-09-03T14:39:09.727Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}