openai/codex · error · std::io::Error

local cwd URI `{cwd_display}` is not absolute: {err}

Error message

local cwd URI `{cwd_display}` is not absolute: {err}

What it means

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.

Source

Thrown at codex-rs/core/src/tools/approvals.rs:364

            },
        })
    }
}

fn guardian_cwd(environment_id: &str, cwd: PathUri) -> std::io::Result<AbsolutePathBuf> {
    match cwd.to_abs_path() {
        Ok(cwd) => Ok(cwd),
        Err(err) if environment_id != codex_exec_server::LOCAL_ENVIRONMENT_ID => Err(err),
        Err(_) => {
            let cwd_display = cwd.to_string();
            let path = cwd.to_url().to_file_path().map_err(|()| {
                std::io::Error::new(
                    std::io::ErrorKind::InvalidInput,
                    format!("local cwd URI `{cwd_display}` is not a host-native path"),
                )
            })?;
            AbsolutePathBuf::from_absolute_path_checked(path).map_err(|err| {
                std::io::Error::new(
                    std::io::ErrorKind::InvalidInput,
                    format!("local cwd URI `{cwd_display}` is not absolute: {err}"),
                )
            })
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum ApprovalReviewer {
    Guardian,
    User,
}

impl ApprovalReviewer {
    fn for_turn(turn: &TurnContext) -> Self {
        Self::for_policy(turn.approval_policy(), turn.config.approvals_reviewer)
    }

View on GitHub (pinned to 339751715c)

Solutions

  1. Send an absolute file URI: file:/// + absolute path (three slashes, empty authority)
  2. Resolve the cwd against its base directory on the client before constructing the PathUri
  3. If consuming URIs from third parties, canonicalize/absolutize (std::fs::canonicalize) before conversion

Example fix

// before
let cwd = PathUri::from("file:projects/demo"); // → not absolute

// after
let cwd = PathUri::from(format!("file:///{}", abs_root.join("projects/demo").display()));
Defensive patterns

Strategy: validation

Validate before calling

// Before sending: guarantee the URI path is absolute
fn absolute_file_uri(path: &std::path::Path) -> Option<String> {
    if !path.is_absolute() { return None; }
    let p = path.to_str()?.replace(' ', "%20");
    Some(format!("file://{p}"))
}

Type guard

fn uri_yields_absolute_path(cwd: &PathUri) -> bool {
    cwd.to_url()
        .to_file_path()
        .ok()
        .is_some_and(|p| p.is_absolute())
}

Try / catch

match guardian_cwd(env_id, cwd.clone()) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidInput && e.to_string().contains("not absolute") => {
        absolutize_and_retry(cwd) // join onto base dir, rebuild file:/// URI
    }
    r => r?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/678a7dc7fb7f6ed4. Report an issue: GitHub.