`[agents.*].config_file` with relative path fails to deserialize: "AbsolutePathBuf deserialized without a base path in agents"

Resolved 💬 1 comment Opened Apr 24, 2026 by tackcrypto1031 Closed Apr 24, 2026

Summary

When ~/.codex/config.toml contains top-level [agents.<role>] tables with a relative config_file, Codex rejects the whole config with:

Invalid configuration: AbsolutePathBuf deserialized without a base path
in `agents`

This manifests as:

  • Desktop app (Windows): "Failed to update model setting / 無法更新模型設定" when switching models in the UI — save aborts because the running config re-deserialize fails.
  • CLI: fails to start at all.

Root cause

agents_toml_from_layer() in codex-rs/core/src/config/agent_roles.rs deserializes the agents table from TomlValue without wrapping the call in an AbsolutePathBufGuard:

fn agents_toml_from_layer(layer_toml: &TomlValue) -> std::io::Result<Option<AgentsToml>> {
    let Some(agents_toml) = layer_toml.get("agents") else { return Ok(None); };
    agents_toml.clone().try_into().map(Some).map_err(...)
}

Compare with parse_agent_role_file_contents(), which correctly sets let _guard = AbsolutePathBufGuard::new(config_base_dir); before deserialization.

Because of the missing guard, AgentRoleToml.config_file: Option<AbsolutePathBuf> fails the "has base path OR is absolute" check in AbsolutePathBuf::deserialize(), even though the field's doc comment says:

Relative paths are resolved relative to the config.toml that defines them.

Reproduction

# ~/.codex/config.toml
[agents.my-role]
description = "x"
config_file = "agents/my-role.toml"   # relative — fails

Run codex or open Desktop → error above.

Workarounds (for affected users)

  1. Rewrite config_file as absolute path, using TOML literal strings to avoid backslash escapes:

``toml
config_file = 'C:\Users\you\.codex\agents\my-role.toml'
``

  1. Or: delete the [agents.<role>] blocks entirely — Codex auto-discovers *.toml under $CODEX_HOME/agents/ via discover_agent_roles_in_dir, so these explicit blocks are redundant.

Suggested fix

Set AbsolutePathBufGuard::new(<config.toml's dir>) before the try_into() in agents_toml_from_layer, matching parse_agent_role_file_contents.

Impact on ecosystem installers

The get-shit-done (GSD) installer writes 18 [agents.gsd-*] blocks with relative config_file = "agents/gsd-*.toml" paths, breaking every user who installs GSD on current Codex. Fixing upstream removes the papercut for all such installers.

Environment

  • OS: Windows 11
  • Codex CLI: 0.124.0 (npm i -g @openai/codex)
  • Codex Desktop (Windows): model switching UI

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗