{"record":{"id":"e806e7133bb852ca","repo":"openai/codex","slug":"snapshot-command-timed-out-for-shell-name","errorCode":null,"errorMessage":"Snapshot command timed out for {shell_name}","messagePattern":"Snapshot command timed out for (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"codex-rs/core/src/shell_snapshot.rs","lineNumber":302,"sourceCode":"\n    // Handler is kept as guard to control the drop. The `mut` pattern is required because .args()\n    // returns a ref of handler.\n    let mut handler = Command::new(&args[0]);\n    codex_protocol::shell_environment::scrub_non_inheritable_env_vars(handler.as_std_mut());\n    handler.args(&args[1..]);\n    handler.stdin(Stdio::null());\n    handler.current_dir(cwd);\n    #[cfg(unix)]\n    unsafe {\n        handler.pre_exec(|| {\n            codex_utils_pty::process_group::detach_from_tty()?;\n            Ok(())\n        });\n    }\n    handler.kill_on_drop(true);\n    let output = timeout(snapshot_timeout, handler.output())\n        .await\n        .map_err(|_| anyhow!(\"Snapshot command timed out for {shell_name}\"))?\n        .with_context(|| format!(\"Failed to execute {shell_name}\"))?;\n\n    if !output.status.success() {\n        let status = output.status;\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        bail!(\"Snapshot command exited with status {status}: {stderr}\");\n    }\n\n    Ok(String::from_utf8_lossy(&output.stdout).into_owned())\n}\n\n/// Removes shell snapshots that either lack a matching session rollout file or\n/// whose rollouts have not been updated within the retention window.\n/// The active session id is exempt from cleanup.\npub async fn cleanup_stale_snapshots(\n    codex_home: &AbsolutePathBuf,\n    active_session_id: ThreadId,\n    state_db: Option<StateDbHandle>,","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/core/src/shell_snapshot.rs#L284-L320","documentation":"run_script_with_timeout wraps the snapshot shell process in tokio::time::timeout with SNAPSHOT_TIMEOUT = 10 seconds (shell_snapshot.rs:45), with kill_on_drop(true) so the child is reaped when the future is dropped. The error fires when sourcing rcfiles plus emitting the snapshot exceeds those 10s. Both snapshot creation and snapshot validation (which re-sources the written file) run through this budget.","triggerScenarios":"Login-shell (-lc) snapshot run where rcfiles take >10s: nvm/pyenv/conda/rbenv init, network calls (version managers, proxy checks, prompt themes fetching data), sleeps, or huge shell histories; also a validation run re-sourcing an enormous generated snapshot.","commonSituations":"Heavy developer dotfiles (nvm.sh alone can take seconds), corporate login scripts, DNS/proxy stalls inside rcfiles, resource-starved CI or containers making shell startup crawl.","solutions":["Time your shell startup (zsh -i -c 'exit' with a prompt timer, or time zsh -lc true) and trim/lazy-load the slow rcfile parts (defer nvm, conda hooks)","Move network-touching init out of rcfiles or cache their results","Skip heavy init when non-interactive so snapshot runs stay lean","If startup legitimately needs more, disable shell snapshots rather than fighting the fixed 10s budget (the timeout constant is not user-configurable)"],"exampleFix":"# ~/.zshrc — before\nsource ~/.nvm/nvm.sh              # seconds of startup cost\n\n# after — lazy-load so snapshot runs stay fast\nif [[ -n \"$USE_NVM\" ]]; then source ~/.nvm/nvm.sh; else\n  nvm() { unfunction nvm; source ~/.nvm/nvm.sh; nvm \"$@\"; }\nfi","handlingStrategy":"fallback","validationCode":"// Measure login-shell startup before enabling snapshots\n// e.g. in shell: TIMEFMT='%E'; time zsh -lc true  — keep it well under the 10s budget","typeGuard":null,"tryCatchPattern":"match try_create(...).await {\n    Err(\"write_failed\") | Err(\"validation_failed\") => {\n        warn_and_continue_without_snapshot(); }\n    ok => ok,\n}","preventionTips":["Keep login-shell startup under a few seconds (lazy-load nvm/conda/pyenv)","Remove network calls from rcfiles or cache their results","The timeout is fixed at 10s (SNAPSHOT_TIMEOUT) — don't design dotfiles that need more","Monitor the codex.shell_snapshot counter with failure_reason tags to catch envs that chronically time out"],"tags":["rust","codex","shell-snapshot","timeout","slow-startup"],"backgroundTag":"command-timeout","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}