openai/codex · error · io::Error
Config file {} has no parent directory
Error message
Config file {} has no parent directory What it means
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.
Source
Thrown at codex-rs/config/src/loader/layer_io.rs:198
} else {
tracing::debug!("{} not found", path.as_path().display());
}
Ok(None)
}
Err(err) => {
tracing::error!("Failed to read {}: {err}", path.as_path().display());
Err(err)
}
}
}
fn validate_config_toml_strictly(
path: &AbsolutePathBuf,
contents: &str,
value: &TomlValue,
) -> io::Result<()> {
let Some(base_dir) = path.as_path().parent() else {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("Config file {} has no parent directory", path.display()),
));
};
let _guard = AbsolutePathBufGuard::new(base_dir);
if let Some(config_error) = config_error_from_ignored_toml_value_fields::<ConfigToml>(
path.as_path(),
contents,
value.clone(),
) {
return Err(io_error_from_config_error(
io::ErrorKind::InvalidData,
config_error,
/*source*/ None,
));
}
Ok(())View on GitHub (pinned to 339751715c)
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
Example fix
// before
let path = AbsolutePathBuf::try_from(env::var("CONFIG").unwrap_or_default())?; // "" or "/"
// after
let dir = env::var("CONFIG").unwrap_or_else(|_| "/etc/codex".into());
let path = AbsolutePathBuf::try_from(PathBuf::from(dir).join("config.toml"))?; Defensive patterns
Strategy: validation
Validate before calling
let Some(_base) = path.as_path().parent() else {
anyhow::bail!(
"config path must be a file inside a directory, got: {}",
path.display()
);
}; Type guard
fn has_parent_dir(p: &std::path::Path) -> bool {
p.parent().is_some()
} Try / catch
match read_config_from_path(&path).await {
Err(e) if e.kind() == io::ErrorKind::InvalidData
&& e.to_string().contains("no parent directory") =>
{
// fix the env var / override that produced the path; do not retry as-is
}
r => r?,
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Managed config file {} has no parent directory
- InvalidData
- approval_policy = "untrusted" is no longer supported; remove
- remote control URL cannot be a base
- InvalidInput
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/44e21abcb2337a2f.
Report an issue: GitHub.