{"id":"a848e905967ee656","repo":"rust-lang/cargo","slug":"can-only-edit-absolute-paths-got","errorCode":null,"errorMessage":"can only edit absolute paths, got {}","messagePattern":"can only edit absolute paths, got (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/workspace/editor/manifest.rs","lineNumber":268,"sourceCode":"impl Deref for LocalManifest {\n    type Target = Manifest;\n\n    fn deref(&self) -> &Manifest {\n        &self.manifest\n    }\n}\n\nimpl DerefMut for LocalManifest {\n    fn deref_mut(&mut self) -> &mut Manifest {\n        &mut self.manifest\n    }\n}\n\nimpl LocalManifest {\n    /// Construct the `LocalManifest` corresponding to the `Path` provided..\n    pub fn try_new(path: &Path) -> CargoResult<Self> {\n        if !path.is_absolute() {\n            anyhow::bail!(\"can only edit absolute paths, got {}\", path.display());\n        }\n        let raw = cargo_util::paths::read(&path)?;\n        let mut data = raw.clone();\n        let mut embedded = None;\n        if is_embedded(path) {\n            let source = ScriptSource::parse(&data)?;\n            if let Some(frontmatter) = source.frontmatter_span() {\n                embedded = Some(Embedded::exists(frontmatter));\n                data = source.frontmatter().unwrap().to_owned();\n            } else if let Some(shebang) = source.shebang_span() {\n                embedded = Some(Embedded::after(shebang));\n                data = String::new();\n            } else {\n                embedded = Some(Embedded::start());\n                data = String::new();\n            }\n        }\n        let manifest = data.parse().context(\"unable to parse Cargo.toml\")?;","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/workspace/editor/manifest.rs#L250-L286","documentation":"Thrown by `LocalManifest::try_new` at src/workspace/editor/manifest.rs:268. The manifest editor (used by `cargo add`, `cargo rm`, and library callers) requires an absolute filesystem path so it can reliably read, normalize, and write back the file. A relative path is rejected immediately before any I/O.","triggerScenarios":"Calling `LocalManifest::try_new(Path::new(\"Cargo.toml\"))` or `try_new(&relative)` from a tool; `cargo add` invoked with a manifest path resolved relative to the wrong cwd.","commonSituations":"Embedding cargo-as-a-library and passing a user-supplied relative path; glue code that joins paths incorrectly; running under a changed working directory.","solutions":["Canonicalize first: `LocalManifest::try_new(&std::fs::canonicalize(p)?)`.","Make the path absolute with the current dir: `let p = std::env::current_dir()?.join(p); LocalManifest::try_new(&p)`.","Ensure callers always pass an absolute path to the editor API."],"exampleFix":"// before\nlet m = LocalManifest::try_new(Path::new(\"Cargo.toml\"))?;\n// after\nlet abs = std::env::current_dir()?.join(\"Cargo.toml\");\nlet m = LocalManifest::try_new(&abs)?;","handlingStrategy":"validation","validationCode":"let abs = if p.is_absolute() { p.to_path_buf() }\n    else { std::env::current_dir()?.join(p) };\nassert!(abs.is_absolute(), \"path must be absolute\");\nlet m = LocalManifest::try_new(&abs)?;","typeGuard":"fn is_absolute_manifest_path(p: &std::path::Path) -> bool { p.is_absolute() }","tryCatchPattern":null,"preventionTips":["Always canonicalize user-supplied paths before the editor API.","Document that `LocalManifest::try_new` requires absolute paths.","Centralize path normalization in one helper used by all callers."],"tags":["api","paths","editor"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}