openai/codex · error · std::io::Error
features.multi_agent_v2.max_concurrent_threads_per_session m
Error message
features.multi_agent_v2.max_concurrent_threads_per_session must be at least 1
What it means
resolve_multi_agent_v2_config reads `[features.multi_agent_v2]`, and Config::load enforces max_concurrent_threads_per_session >= 1 because a session must allow at least one concurrent subagent thread. Defaults are non-zero, so hitting this means the key was explicitly set to 0 in some layer.
Source
Thrown at codex-rs/core/src/config/mod.rs:3710
let model_provider = model_providers
.get(&model_provider_id)
.ok_or_else(|| {
let message = if model_provider_id == LEGACY_OLLAMA_CHAT_PROVIDER_ID {
OLLAMA_CHAT_PROVIDER_REMOVED_ERROR.to_string()
} else {
format!("Model provider `{model_provider_id}` not found")
};
std::io::Error::new(std::io::ErrorKind::NotFound, message)
})?
.clone();
let shell_environment_policy = cfg.shell_environment_policy.into();
let allow_login_shell = cfg.allow_login_shell.unwrap_or(true);
let history = cfg.history.unwrap_or_default();
if multi_agent_v2.max_concurrent_threads_per_session == 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"features.multi_agent_v2.max_concurrent_threads_per_session must be at least 1",
));
}
validate_multi_agent_v2_wait_timeout(
"features.multi_agent_v2.min_wait_timeout_ms",
multi_agent_v2.min_wait_timeout_ms,
)?;
validate_multi_agent_v2_wait_timeout(
"features.multi_agent_v2.max_wait_timeout_ms",
multi_agent_v2.max_wait_timeout_ms,
)?;
validate_multi_agent_v2_wait_timeout(
"features.multi_agent_v2.default_wait_timeout_ms",
multi_agent_v2.default_wait_timeout_ms,
)?;
if multi_agent_v2.min_wait_timeout_ms > multi_agent_v2.max_wait_timeout_ms {
return Err(std::io::Error::new(View on GitHub (pinned to 339751715c)
Solutions
- Set `max_concurrent_threads_per_session = 1` (serial subagent execution) or higher.
- Or delete the key to fall back to the built-in default.
- If the goal is to turn the feature off, disable the multi_agent_v2 feature rather than zeroing the limit.
Example fix
# before [features.multi_agent_v2] max_concurrent_threads_per_session = 0 # after [features.multi_agent_v2] max_concurrent_threads_per_session = 1
Defensive patterns
Strategy: validation
Validate before calling
import tomllib
cfg = tomllib.load(open("config.toml", "rb"))
ma = cfg.get("features", {}).get("multi_agent_v2", {})
limit = ma.get("max_concurrent_threads_per_session")
assert limit is None or limit >= 1, "max_concurrent_threads_per_session must be >= 1" Try / catch
match config_result {
Err(ref e) if e.kind() == std::io::ErrorKind::InvalidInput
&& e.to_string().contains("features.multi_agent_v2.max_concurrent_threads_per_session") => {
// clamp to 1 or drop the key, then retry
}
other => other,
} Prevention
- Treat 0 as invalid for concurrency limits; use feature switches to disable
- Validate numeric feature knobs when generating configs
- Remember the same rule applies to the [agents] twin of this setting
When it happens
Trigger: `[features.multi_agent_v2]` with `max_concurrent_threads_per_session = 0` in ~/.codex/config.toml, a project layer, or a managed layer. Fires during Config::load after model-provider resolution.
Common situations: Trying to disable multi-agent v2 by zeroing the limit instead of using the feature's enable switch; copy-paste from tuned examples; a managed layer zeroing the knob globally.
Related errors
- Invalid MCP server name '{server_name}': must match pattern
- config defines `[permissions]` profiles but does not set `de
- features.multi_agent_v2.min_wait_timeout_ms must be at most
- features.multi_agent_v2.default_wait_timeout_ms must be at l
- features.multi_agent_v2.default_wait_timeout_ms must be at m
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/b689431bec717159.
Report an issue: GitHub.