{"record":{"id":"678a7dc7fb7f6ed4","repo":"openai/codex","slug":"local-cwd-uri-cwd-display-is-not-absolute-er","errorCode":null,"errorMessage":"local cwd URI `{cwd_display}` is not absolute: {err}","messagePattern":"local cwd URI `(.+?)` is not absolute: (.+?)","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/core/src/tools/approvals.rs","lineNumber":364,"sourceCode":"            },\n        })\n    }\n}\n\nfn guardian_cwd(environment_id: &str, cwd: PathUri) -> std::io::Result<AbsolutePathBuf> {\n    match cwd.to_abs_path() {\n        Ok(cwd) => Ok(cwd),\n        Err(err) if environment_id != codex_exec_server::LOCAL_ENVIRONMENT_ID => Err(err),\n        Err(_) => {\n            let cwd_display = cwd.to_string();\n            let path = cwd.to_url().to_file_path().map_err(|()| {\n                std::io::Error::new(\n                    std::io::ErrorKind::InvalidInput,\n                    format!(\"local cwd URI `{cwd_display}` is not a host-native path\"),\n                )\n            })?;\n            AbsolutePathBuf::from_absolute_path_checked(path).map_err(|err| {\n                std::io::Error::new(\n                    std::io::ErrorKind::InvalidInput,\n                    format!(\"local cwd URI `{cwd_display}` is not absolute: {err}\"),\n                )\n            })\n        }\n    }\n}\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\nenum ApprovalReviewer {\n    Guardian,\n    User,\n}\n\nimpl ApprovalReviewer {\n    fn for_turn(turn: &TurnContext) -> Self {\n        Self::for_policy(turn.approval_policy(), turn.config.approvals_reviewer)\n    }","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/core/src/tools/approvals.rs#L346-L382","documentation":"The second-stage failure in guardian_cwd: for a LOCAL environment, PathUri::to_abs_path() failed, but the URL did convert to a filesystem path via to_file_path(); that path is then handed to AbsolutePathBuf::from_absolute_path_checked, which rejects non-absolute paths. This io::Error(InvalidInput) therefore means the URI produced a relative path — typically a file: URI without the leading slash or a dot/parent-relative form.","triggerScenarios":"An approval request with a local cwd PathUri like 'file:relative/path', 'file:./build', 'file:../repo', or any file URL whose path component does not begin with a root slash.","commonSituations":"Hand-built URIs joining a scheme onto a relative path; URI-encoding bugs dropping the leading '/'; clients assuming cwd is resolved against some base and sending it un-resolved.","solutions":["Send an absolute file URI: file:/// + absolute path (three slashes, empty authority)","Resolve the cwd against its base directory on the client before constructing the PathUri","If consuming URIs from third parties, canonicalize/absolutize (std::fs::canonicalize) before conversion"],"exampleFix":"// before\nlet cwd = PathUri::from(\"file:projects/demo\"); // → not absolute\n\n// after\nlet cwd = PathUri::from(format!(\"file:///{}\", abs_root.join(\"projects/demo\").display()));","handlingStrategy":"validation","validationCode":"// Before sending: guarantee the URI path is absolute\nfn absolute_file_uri(path: &std::path::Path) -> Option<String> {\n    if !path.is_absolute() { return None; }\n    let p = path.to_str()?.replace(' ', \"%20\");\n    Some(format!(\"file://{p}\"))\n}","typeGuard":"fn uri_yields_absolute_path(cwd: &PathUri) -> bool {\n    cwd.to_url()\n        .to_file_path()\n        .ok()\n        .is_some_and(|p| p.is_absolute())\n}","tryCatchPattern":"match guardian_cwd(env_id, cwd.clone()) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains(\"not absolute\") => {\n        absolutize_and_retry(cwd) // join onto base dir, rebuild file:/// URI\n    }\n    r => r?,\n}","preventionTips":["Always emit three slashes: file:///abs/path","Resolve relative cwds against their base directory client-side before URI construction","Unit-test URI builders to reject relative path components"],"tags":["rust","codex","approvals","cwd","relative-path","path-validation"],"backgroundTag":"relative-path-where-absolute-required","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}