{"record":{"id":"e2577313ab8e8641","repo":"gitbutlerapp/gitbutler","slug":"not-found","errorCode":null,"errorMessage":"{} not found","messagePattern":"(.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-filemonitor/src/file_monitor.rs","lineNumber":579,"sourceCode":"            )\n    )\n}\n\n#[cfg(target_os = \"windows\")]\nfn is_interesting_kind(kind: notify::EventKind) -> bool {\n    matches!(\n        kind,\n        notify::EventKind::Create(_) | notify::EventKind::Modify(_) | notify::EventKind::Remove(_)\n    )\n}\n\nfn into_backoff_err(\n    err: notify::Error,\n    path: &Path,\n) -> backoff::Error<Box<dyn std::error::Error + Send + Sync + 'static>> {\n    match err.kind {\n        notify::ErrorKind::PathNotFound => backoff::Error::permanent(\n            anyhow!(\"{} not found\", path.display()).into_boxed_dyn_error(),\n        ),\n        notify::ErrorKind::Io(_) | notify::ErrorKind::InvalidConfig(_) => {\n            backoff::Error::permanent(anyhow::Error::from(err).into_boxed_dyn_error())\n        }\n        _ => backoff::Error::transient(anyhow::Error::from(err).into_boxed_dyn_error()),\n    }\n}\n\nfn backoff_err_to_anyhow(\n    err: backoff::Error<Box<dyn std::error::Error + Send + Sync + 'static>>,\n) -> anyhow::Error {\n    anyhow::Error::from_boxed(Box::from(err.to_string()))\n}\n\npub const LOCAL_REFS_DIR: &str = \"refs/heads/\";\npub const REMOTE_REFS_DIR: &str = \"refs/remotes/\";\npub const FETCH_HEAD: &str = \"FETCH_HEAD\";\npub const HEAD: &str = \"HEAD\";","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/gitbutler-filemonitor/src/file_monitor.rs#L561-L597","documentation":"Converts a notify (filesystem watcher) error into a backoff error. notify::ErrorKind::PathNotFound becomes a permanent backoff error with the message '<path> not found', so retries are skipped. Other IO/invalid-config errors are also permanent; everything else is transient.","triggerScenarios":"Setting up a watch (setup_watch_plan / setup_legacy_watch) on a directory that does not exist or was deleted before/while watching — e.g. the workspace/project directory moved or removed.","commonSituations":"Project folder deleted or renamed externally while the app runs; watching a nested path removed during a git operation (checkout/clean); passing a stale path after re-cloning.","solutions":["Verify the watched path exists before setting up the watch (fs::metadata).","Re-point the watch to the current valid project directory.","If the path is expected to appear later, defer watch setup until it exists (this error is permanent and will not retry).","Check whether a git operation (checkout/clean) removed the directory and re-establish the watch afterward."],"exampleFix":"// before\nwatcher.watch(&project_path, Recursive)?;\n// after\nif project_path.exists() {\n    watcher.watch(&project_path, Recursive)?;\n}","handlingStrategy":"validation","validationCode":"if !path.is_dir() {\n    return Err(anyhow!(\"cannot watch missing directory: {}\", path.display()));\n}\n// now safe to set up the watch","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always check the target path exists before installing a watcher.","Re-create watchers after git operations that can replace directories.","Treat PathNotFound as permanent — do not rely on backoff retries for it."],"tags":["filesystem","watcher","path-not-found"],"backgroundTag":"file-not-found","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}