{"record":{"id":"44e21abcb2337a2f","repo":"openai/codex","slug":"config-file-has-no-parent-directory","errorCode":null,"errorMessage":"Config file {} has no parent directory","messagePattern":"Config file (.+?) has no parent directory","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"codex-rs/config/src/loader/layer_io.rs","lineNumber":198,"sourceCode":"            } else {\n                tracing::debug!(\"{} not found\", path.as_path().display());\n            }\n            Ok(None)\n        }\n        Err(err) => {\n            tracing::error!(\"Failed to read {}: {err}\", path.as_path().display());\n            Err(err)\n        }\n    }\n}\n\nfn validate_config_toml_strictly(\n    path: &AbsolutePathBuf,\n    contents: &str,\n    value: &TomlValue,\n) -> io::Result<()> {\n    let Some(base_dir) = path.as_path().parent() else {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\"Config file {} has no parent directory\", path.display()),\n        ));\n    };\n    let _guard = AbsolutePathBufGuard::new(base_dir);\n    if let Some(config_error) = config_error_from_ignored_toml_value_fields::<ConfigToml>(\n        path.as_path(),\n        contents,\n        value.clone(),\n    ) {\n        return Err(io_error_from_config_error(\n            io::ErrorKind::InvalidData,\n            config_error,\n            /*source*/ None,\n        ));\n    }\n\n    Ok(())","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/config/src/loader/layer_io.rs#L180-L216","documentation":"validate_config_toml_strictly (codex-rs/config/src/loader/layer_io.rs:192) needs the config file's parent directory to install an AbsolutePathBufGuard, the base against which relative paths in the TOML are resolved. If Path::parent() returns None (the path is a filesystem root like / or the empty string), it returns ErrorKind::InvalidData with this message. read_config_from_path reaches it whenever strict config checking is enabled.","triggerScenarios":"read_config_from_path invoked in strict mode with a path whose parent is None: literally '/', a Windows drive root, or an empty path. Usually the result of a mis-set CODEX_HOME, a --config-path style override, or joining onto an empty directory variable.","commonSituations":"A wrapper script or env var resolves to / or empty; container images setting the config location to the filesystem root; config path construction that skips appending the filename when a variable is empty.","solutions":["Point the config path at a real file inside a directory (e.g. /etc/codex/config.toml), never at a filesystem root or empty string","Echo and fix the env var or CLI override that produced the degenerate path","Guard path construction so empty dir variables fall back to a sane default before the filename is appended"],"exampleFix":"// before\nlet path = AbsolutePathBuf::try_from(env::var(\"CONFIG\").unwrap_or_default())?; // \"\" or \"/\"\n\n// after\nlet dir = env::var(\"CONFIG\").unwrap_or_else(|_| \"/etc/codex\".into());\nlet path = AbsolutePathBuf::try_from(PathBuf::from(dir).join(\"config.toml\"))?;","handlingStrategy":"validation","validationCode":"let Some(_base) = path.as_path().parent() else {\n    anyhow::bail!(\n        \"config path must be a file inside a directory, got: {}\",\n        path.display()\n    );\n};","typeGuard":"fn has_parent_dir(p: &std::path::Path) -> bool {\n    p.parent().is_some()\n}","tryCatchPattern":"match read_config_from_path(&path).await {\n    Err(e) if e.kind() == io::ErrorKind::InvalidData\n        && e.to_string().contains(\"no parent directory\") =>\n    {\n        // fix the env var / override that produced the path; do not retry as-is\n    }\n    r => r?,\n}","preventionTips":["Assert config paths are absolute and non-root at construction time","Validate env-var-derived paths at startup with a clear error","Never pass a directory or filesystem root where a file path is expected"],"tags":["config","loader","filesystem","path","rust"],"backgroundTag":"invalid-file-path","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}