{"record":{"id":"73319f2613aad4df","repo":"rust-lang/mdBook","slug":"output-html-search-chapter-key-does-not-mat","errorCode":null,"errorMessage":"[output.html.search.chapter] key `{}` does not match any chapter paths","messagePattern":"\\[output\\.html\\.search\\.chapter\\] key `(.+?)` does not match any chapter paths","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mdbook-html/src/html_handlebars/search.rs","lineNumber":288,"sourceCode":"    Ok(json_contents)\n}\n\nfn settings_path(ch: &Chapter) -> &Path {\n    ch.source_path\n        .as_deref()\n        .unwrap_or_else(|| ch.path.as_deref().unwrap())\n}\n\nfn validate_chapter_config(\n    chapter_configs: &[(PathBuf, SearchChapterSettings)],\n    chapter_trees: &[ChapterTree<'_>],\n) -> Result<()> {\n    for (path, _) in chapter_configs {\n        let found = chapter_trees\n            .iter()\n            .any(|ct| settings_path(ct.chapter).starts_with(path));\n        if !found {\n            bail!(\n                \"[output.html.search.chapter] key `{}` does not match any chapter paths\",\n                path.display()\n            );\n        }\n    }\n    Ok(())\n}\n\nfn sort_search_config(\n    map: &HashMap<String, SearchChapterSettings>,\n) -> Vec<(PathBuf, SearchChapterSettings)> {\n    let mut settings: Vec<_> = map\n        .iter()\n        .map(|(key, value)| (PathBuf::from(key), value.clone()))\n        .collect();\n    // Note: This is case-sensitive, and assumes the author uses the same case\n    // as the actual filename.\n    settings.sort_by(|a, b| a.0.cmp(&b.0));","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/rust-lang/mdBook/blob/dc21064fc21d955a0e1f67e65e336883c3e5260b/crates/mdbook-html/src/html_handlebars/search.rs#L270-L306","documentation":"output.html.search.chapter-* settings let users tweak per-chapter search behavior keyed by chapter path. validate_chapter_config iterates those keys and fails if a key does not prefix-match any path in the chapter tree, catching typos before generating search files.","triggerScenarios":"Setting a key under [output.html.search.chapter] such as \"some/chapter.md\" (or a sub-table) whose path doesn't match (starts_with) any chapter's settings path computed from the SUMMARY tree.","commonSituations":"Typos in chapter paths; using absolute or OS-style paths instead of the source-relative form; renaming/moving a markdown file without updating the search.chapter key; enabling/disabling search on a deleted chapter.","solutions":["Fix the key in book.toml so it matches an actual chapter source path exactly as mdBook normalizes it (source-relative path).","Remove the stale [output.html.search.chapter] entry for the renamed or deleted chapter.","List the chapter tree (e.g. inspect SUMMARY.md) and copy the exact paths into the config."],"exampleFix":"// before (book.toml)\n[output.html.search.chapter.intro]\nenable = false\n\n// after (matching src/introduction.md)\n[output.html.search.chapter.introduction]\nenable = false","handlingStrategy":"validation","validationCode":"// Verify search.chapter keys against SUMMARY source paths\nfor (const key of Object.keys(config['output.html.search.chapter'] || {})) {\n  if (!sourcePaths.some(p => p === key || p.startsWith(key))) {\n    throw new Error(`search.chapter key ${key} matches no chapter`);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy chapter keys directly from SUMMARY.md paths.","Update [output.html.search.chapter] whenever renaming or moving chapters."],"tags":["config","search","validation","mdbook"],"backgroundTag":"config-key-not-found","analyzedSha":"dc21064fc21d955a0e1f67e65e336883c3e5260b","analyzedAt":"2026-09-01T10:15:12.134Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}