openai/codex · error · anyhow::Error
zsh fork feature enabled, but packaged zsh fork `{}` is not
Error message
zsh fork feature enabled, but packaged zsh fork `{}` is not usable What it means
Codex fails during session construction (session.rs) when the experimental zsh fork shell feature (Feature::ShellZshFork) is enabled in config.features. The code first requires config.zsh_path to be Some (a separate error covers the None case), then checks zsh_path.is_file(); if the packaged zsh binary is missing it falls back to shell::get_shell(ShellType::Zsh), which searches the system for zsh. This error means BOTH failed: the packaged zsh fork at the printed path is not a usable file AND no system zsh could be located. The session cannot start until the shell is resolvable.
Source
Thrown at codex-rs/core/src/session/session.rs:1158
let use_zsh_fork_shell = config.features.enabled(Feature::ShellZshFork);
let default_shell = if let Some(user_shell_override) =
session_configuration.user_shell_override.clone()
{
user_shell_override
} else if use_zsh_fork_shell {
let zsh_path = config.zsh_path.as_ref().ok_or_else(|| {
anyhow::anyhow!(
"zsh fork feature enabled, but no packaged zsh fork is available for this install"
)
})?;
if zsh_path.is_file() {
shell::Shell {
shell_type: shell::ShellType::Zsh,
shell_path: zsh_path.clone(),
}
} else {
shell::get_shell(shell::ShellType::Zsh).ok_or_else(|| {
anyhow::anyhow!(
"zsh fork feature enabled, but packaged zsh fork `{}` is not usable",
zsh_path.display()
)
})?
}
} else {
shell::default_user_shell()
};
let use_executor_shell_snapshots = config.features.enabled(Feature::ShellSnapshotV2)
&& config.features.enabled(Feature::ShellTool)
&& config.features.enabled(Feature::UnifiedExec)
&& matches!(
codex_tools::UnifiedExecShellMode::for_session(
config.features.get(),
crate::tools::tool_user_shell_type(&default_shell),
config.zsh_path.as_ref(),
config.main_execve_wrapper_exe.as_ref(),
),View on GitHub (pinned to 339751715c)
Solutions
- Check the exact path printed in the error (ls -l <path>) and reinstall or update the Codex install so the packaged zsh fork exists there
- If the file exists, fix usability: chmod +x it, and on macOS run xattr -d com.apple.quarantine <path>
- Install a system zsh (brew install zsh / apt install zsh) so the get_shell(ShellType::Zsh) fallback succeeds
- If neither is possible, disable the feature by removing the zsh fork flag from features config so the default user shell is used
Example fix
// config.toml — before [features] shell_zsh_fork = true // after (no packaged/system zsh available) [features] # shell_zsh_fork = true // disabled; fall back to default_user_shell()
Defensive patterns
Strategy: validation
Validate before calling
// Run before session construction / before enabling the zsh fork feature
fn zsh_fork_ready(cfg_zsh_path: Option<&std::path::Path>) -> bool {
match cfg_zsh_path {
Some(p) if p.is_file() => true,
_ => codex_core::shell::get_shell(codex_core::shell::ShellType::Zsh).is_some(),
}
} Type guard
fn usable_zsh_available(zsh_path: Option<&std::path::Path>) -> bool {
zsh_path.is_some_and(|p| p.is_file())
|| codex_core::shell::get_shell(codex_core::shell::ShellType::Zsh).is_some()
} Try / catch
// Session construction returns anyhow::Result — surface it, don't unwrap:
match Session::new(config).await {
Err(e) if e.to_string().contains("zsh fork") => { /* disable feature or guide install */ }
other => other?,
} Prevention
- Verify the packaged zsh fork file exists and is executable after every install/update
- Keep a system zsh on PATH (brew/apt) so the get_shell fallback can rescue a missing packaged binary
- Gate experimental feature flags in config behind a preflight check in test/CI environments
- Don't enable shell_zsh_fork in shared configs for machines whose installs don't bundle the zsh payload
When it happens
Trigger: Enabling the zsh fork feature flag in config (e.g. [features] shell_zsh_fork) while (a) the install's packaged zsh fork binary at config.zsh_path has been deleted, moved, corrupted, or never downloaded, AND (b) no zsh exists on PATH so get_shell(ShellType::Zsh) returns None.
Common situations: Partial or interrupted install/update that dropped the bundled zsh fork; custom CODEX_HOME pointing at a directory that lacks the zsh payload; dev builds that never bundle zsh; macOS quarantine (com.apple.quarantine) or missing execute bit making the file unusable; sandboxed/scrubbed environments where PATH has no zsh.
Related errors
- unknown environment shell `{name}`
- pid-managed app-server shutdown is unsupported on this platf
- pid-managed updater shutdown is unsupported on this platform
- failed to read start time for pid-managed app server {pid}
- pid-managed app server {pid} has no recorded start time
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/2efafe728326c2e7.
Report an issue: GitHub.