{"record":{"id":"789e5ee8afaf2b2a","repo":"rust-lang/mdBook","slug":"ignore-root-canonicalize-error","errorCode":null,"errorMessage":"ignore root canonicalize error","messagePattern":"ignore root canonicalize error","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/watch/native.rs","lineNumber":136,"sourceCode":"                    gitignore_path.display()\n                );\n            }\n            filter_ignored_files(ignore, paths)\n        }\n        None => {\n            // There is no .gitignore file.\n            paths.iter().map(|path| path.to_path_buf()).collect()\n        }\n    }\n}\n\n// Note: The usage of `canonicalize` may encounter occasional failures on the Windows platform, presenting a potential risk.\n// For more details, refer to [Pull Request #2229](https://github.com/rust-lang/mdBook/pull/2229#discussion_r1408665981).\nfn filter_ignored_files(ignore: Gitignore, paths: &[PathBuf]) -> Vec<PathBuf> {\n    let ignore_root = ignore\n        .path()\n        .canonicalize()\n        .expect(\"ignore root canonicalize error\");\n\n    paths\n        .iter()\n        .filter(|path| {\n            let relative_path = pathdiff::diff_paths(&path, &ignore_root)\n                .expect(\"One of the paths should be an absolute\");\n            !ignore\n                .matched_path_or_any_parents(&relative_path, relative_path.is_dir())\n                .is_ignore()\n        })\n        .map(|path| path.to_path_buf())\n        .collect()\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use ignore::gitignore::GitignoreBuilder;","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/rust-lang/mdBook/blob/dc21064fc21d955a0e1f67e65e336883c3e5260b/src/cmd/watch/native.rs#L118-L154","documentation":"In native.rs `filter_ignored_files`, the gitignore root path is canonicalized with `.expect(\"ignore root canonicalize error\")`, so if `Path::canonicalize` fails (typically because the ignore root does not exist, or on Windows where canonicalize is flaky per PR #2229 discussion) the program panics. The comment in the source explicitly flags the Windows fragility risk.","triggerScenarios":"`mdbook watch` building its ignore filter when `ignore.path()` (the directory the .gitignore was loaded from) cannot be canonicalized: the directory was deleted/moved after parsing, a broken symlink, or a Windows canonicalize failure (network drives, case/path-form quirks).","commonSituations":"Watching a book directory that gets renamed or removed while watch is running; book root on a network/UNC path on Windows; symlinked book roots.","solutions":["Ensure the book root (where .gitignore lives) exists and is accessible before running `mdbook watch`.","Avoid running watch against paths on network drives / UNC paths on Windows.","Replace the `.expect` with graceful handling, e.g. fall back to the non-canonicalized path.","Update mdbook to a version where watch ignore handling tolerates canonicalize failure."],"exampleFix":"// before\nlet ignore_root = ignore.path().canonicalize().expect(\"ignore root canonicalize error\");\n// after\nlet ignore_root = ignore\n    .path()\n    .canonicalize()\n    .unwrap_or_else(|_| ignore.path().to_path_buf());","handlingStrategy":"fallback","validationCode":"let ignore_root_raw = ignore.path();\nif !ignore_root_raw.exists() {\n    eprintln!(\"ignore root missing: {:?}\", ignore_root_raw);\n    std::process::exit(1);\n}\nlet canonical = ignore_root_raw.canonicalize(); // check Result before depending on it","typeGuard":null,"tryCatchPattern":"// expect() panics, so guard at the boundary:\nlet ignore_root = ignore.path().canonicalize().unwrap_or_else(|e| {\n    log::warn!(\"canonicalize failed ({e}); using raw path\");\n    ignore.path().to_path_buf()\n});","preventionTips":["Don't delete/rename the book root while `mdbook watch` runs.","Avoid UNC/network-drive roots on Windows.","Prefer canonical, symlink-free book directories.","Patch expects into graceful fallbacks when vendoring this code."],"tags":["filesystem","panic","windows","canonicalize","watch"],"backgroundTag":"path-canonicalize-failed","analyzedSha":"dc21064fc21d955a0e1f67e65e336883c3e5260b","analyzedAt":"2026-09-01T10:15:12.134Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}