rust-lang/mdBook · error

One of the paths should be an absolute

Error message

One of the paths should be an absolute

What it means

`filter_ignored_files` computes each event path relative to the canonicalized ignore root using `pathdiff::diff_paths` and unwraps with `.expect("One of the paths should be an absolute")`. diff_paths returns None when both paths can't be made relative (e.g. one relative and one absolute, or differing Windows prefixes/drives), and this expect turns that into a panic.

Source

Thrown at src/cmd/watch/native.rs:142

            // There is no .gitignore file.
            paths.iter().map(|path| path.to_path_buf()).collect()
        }
    }
}

// Note: The usage of `canonicalize` may encounter occasional failures on the Windows platform, presenting a potential risk.
// For more details, refer to [Pull Request #2229](https://github.com/rust-lang/mdBook/pull/2229#discussion_r1408665981).
fn filter_ignored_files(ignore: Gitignore, paths: &[PathBuf]) -> Vec<PathBuf> {
    let ignore_root = ignore
        .path()
        .canonicalize()
        .expect("ignore root canonicalize error");

    paths
        .iter()
        .filter(|path| {
            let relative_path = pathdiff::diff_paths(&path, &ignore_root)
                .expect("One of the paths should be an absolute");
            !ignore
                .matched_path_or_any_parents(&relative_path, relative_path.is_dir())
                .is_ignore()
        })
        .map(|path| path.to_path_buf())
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    use ignore::gitignore::GitignoreBuilder;
    use std::env;

    #[test]
    fn test_filter_ignored_files() {
        let current_dir = env::current_dir().unwrap();

View on GitHub (pinned to dc21064fc2)

Solutions

  1. Canonicalize event paths before diffing (poller.rs does exactly this: `path.canonicalize().unwrap_or_else(|_| path.to_path_buf())`).
  2. Keep the book and its .gitignore on the same drive/prefix on Windows.
  3. Replace the expect with a `filter_map`/`unwrap_or` that skips or retains the path when diff_paths returns None.
  4. Check for symlinked book roots producing non-matching path prefixes.

Example fix

// before
let relative_path = pathdiff::diff_paths(&path, &ignore_root)
    .expect("One of the paths should be an absolute");
// after
let Some(relative_path) = pathdiff::diff_paths(&path, &ignore_root) else {
    return true; // keep path when it cannot be made relative to ignore root
};
Defensive patterns

Strategy: fallback

Validate before calling

// pre-check before diffing
fn diffable(path: &Path, root: &Path) -> bool {
    path.is_absolute() == root.is_absolute()
        && path.components().next() == root.components().next() // same prefix/drive
}

Try / catch

let relative_path = match pathdiff::diff_paths(&path, &ignore_root) {
    Some(p) => p,
    None => return true, // or skip, instead of panicking
};

Prevention

When it happens

Trigger: A watch-event path and the canonicalized ignore root live under different drives/prefixes (Windows C: vs D:, UNC vs drive), or an event path is relative while the ignore root is absolute, so `diff_paths(path, ignore_root)` returns None.

Common situations: Windows cross-drive book/ignore locations; notify event paths delivered in a different form than the canonicalized root; symlinked directories causing prefix mismatch.

Related errors


AI-assisted analysis of rust-lang/mdBook@dc21064fc2 (2026-09-01). Data as JSON: /api/errors/535ffed0a8f2b9ed. Report an issue: GitHub.