{"record":{"id":"f5b15112b1073a20","repo":"herdrdev/herdr","slug":"failed-to-operation-managed-plugin-checkout-at","errorCode":null,"errorMessage":"failed to {operation} managed plugin checkout at {}; close any Herdr plugin panes or plugin commands using that checkout, then retry: {err}","messagePattern":"failed to (.+?) managed plugin checkout at (.+?); close any Herdr plugin panes or plugin commands using that checkout, then retry: (.+?)","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"warning","filePath":"src/cli/plugin.rs","lineNumber":1591,"sourceCode":"        return Ok(());\n    };\n    let path = PathBuf::from(path);\n    if !path.exists() {\n        return Ok(());\n    }\n    if !is_expected_managed_path(plugin, &path) {\n        return Err(std::io::Error::other(format!(\n            \"refusing to delete unmanaged plugin path: {}\",\n            path.display()\n        )));\n    }\n    std::fs::remove_dir_all(&path)\n        .map_err(|err| plugin_checkout_lifecycle_error(\"remove\", &path, err))\n}\n\nfn plugin_checkout_lifecycle_error(operation: &str, path: &Path, err: io::Error) -> io::Error {\n    if cfg!(windows) && err.kind() == io::ErrorKind::PermissionDenied {\n        return io::Error::new(\n            err.kind(),\n            format!(\n                \"failed to {operation} managed plugin checkout at {}; close any Herdr plugin panes or plugin commands using that checkout, then retry: {err}\",\n                path.display()\n            ),\n        );\n    }\n    err\n}\n\nfn is_expected_managed_path(plugin: &InstalledPluginInfo, path: &Path) -> bool {\n    let Ok(path) = path.canonicalize() else {\n        return false;\n    };\n    let expected = crate::plugin_paths::managed_checkout_path(&plugin.plugin_id);\n    let Ok(expected) = expected.canonicalize() else {\n        return false;\n    };","sourceCodeStart":1573,"sourceCodeEnd":1609,"githubUrl":"https://github.com/herdrdev/herdr/blob/f457cff4f2648eee85d176f8a41861241d4e8428/src/cli/plugin.rs#L1573-L1609","documentation":"plugin_checkout_lifecycle_error (src/cli/plugin.rs:1591) wraps filesystem errors from creating/removing managed plugin checkout directories. On Windows, when the raw error is PermissionDenied, it returns a richer message telling you that a Herdr plugin pane or plugin command still holds the checkout open. Other platforms surface the raw fs error unchanged.","triggerScenarios":"Calling the checkout remove/create path (e.g. std::fs::remove_dir_all at src/cli/plugin.rs:1588-1590, or the corresponding create) on Windows while a process still has files in the checkout open — a running plugin pane, a plugin command shell, an editor, or antivirus scanning the tree.","commonSituations":"Uninstalling/updating a plugin while its pane is open in another Herdr tab; a build process (cargo/node) still running in the checkout; Windows Defender or a file indexer locking files; the directory being open in Explorer.","solutions":["Close all Herdr plugin panes and any terminals/editors using that checkout, then retry the operation","Stop builds or dev servers running inside the plugin checkout","Retry after a short delay if antivirus/indexing was transiently locking files","As a last resort, restart Herdr so all child processes release handles, then retry"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for attempt in 0..3 {\n    match remove_checkout(&path) {\n        Ok(()) => break,\n        Err(e) if cfg!(windows) && e.kind() == io::ErrorKind::PermissionDenied => {\n            std::thread::sleep(std::time::Duration::from_secs(1 << attempt));\n        }\n        Err(e) => return Err(e),\n    }\n}","preventionTips":["Close plugin panes and stop builds before uninstalling or updating plugins","Treat Windows PermissionDenied on directory removal as transient and retry after closing handles"],"tags":["windows","filesystem","file-lock","plugin","rust"],"backgroundTag":"file-locked-by-process","analyzedSha":"f457cff4f2648eee85d176f8a41861241d4e8428","analyzedAt":"2026-08-28T15:41:09.197Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}