codex-rs: codex cannot obtain error information when receiving non-zero exit codes
What version of Codex is running?
codex-cli 0.0.0 (Rust version build from source b73426c1c40187ca13c74c03912a681072c2884f)
Which model were you using?
codex-mini-latest
What platform is your computer?
Linux 6.14.9-300.fc42.x86_64 x86_64 unknown
What steps can reproduce the bug?
- Use codex-rs with any command that produces useful stderr output but exits with non-zero code
- For example, run a linting tool like
flake8that finds errors:
``bash``
codex "run flake8 on my Python files"
# Agent executes: flake8
- When
flake8finds style violations, it exits with code 1 and outputs detailed error messages to stdout (or stderr I'm not sure) - However, codex-rs only knows that the command failed without getting the actual error details
What is the expected behavior?
When a shell command exits with a non-zero code, codex-rs should still get the stderr/stdout output so codex itself can see:
- Detailed error messages from linting tools (flake8, eslint, etc.)
- Compilation error details from build tools
- Test failure specifics from testing frameworks
- Any other diagnostic information that helps understand what went wrong
What do you see instead?
When codex receives a non-zero exit code while executing certain commands but does not receive any information, it starts checking the status of the tools and may find some workarounds on its own. Most of the time, it writes the output to physical files and reads them, which results in many unnecessary files being generated within the project.
Additional information
Current Workaround
Adding || true to shell commands forces the exit code to 0, which allows the output to be displayed:
# Instead of: flake8 --config .flake8 file.py
# Use: flake8 --config .flake8 file.py || true
This workaround preserves the tool's output while ensuring codex-rs doesn't hide it due to the non-zero exit code.
Root Cause Analysis
[!WARNING] The "causes" in this section were generated with AI, and I do not have the knowledge to verify the accuracy. Please use it for reference only and make your own judgment. I hope they can save the community time.
Based on examination of the codex repository source code, this issue stems from how both codex-rs and codex-cli handle container.exec and shell tool calls when exit_code != 0.
Technical Details from Source Code Analysis
In codex-rs (codex-rs/core/src/codex.rs):
- The
handle_container_exec_with_paramsfunction processes shell commands - When
exit_code != 0, the system treats this as a failure condition - The error handling logic appears to suppress stdout/stderr output in favor of showing only error status
In codex-cli (TypeScript/Node.js version):
- Located in files like
codex-cli/src/utils/agent/sandbox/raw-exec.tsandhandle-exec-command.ts - Contains comments explicitly stating: "This function should never return a rejected promise: errors should be mapped to a non-zero exit code and the error message should be in stderr"
- The
exec()function and related command execution pipeline follow a pattern where non-zero exit codes trigger error handling that may hide the actual command output - Function signatures and logic in
agent-loop.tsshow tool dispatch handling that differentiates between "successful" (exit code 0) and "failed" (exit code ≠ 0) commands
The Core Problem
Both implementations seem to follow this problematic logic:
- Execute shell command via
container.execor similar mechanism - Check exit code
- If
exit_code == 0: Display stdout/stderr normally - If
exit_code != 0: Treat as "error" and suppress detailed output
However, many development tools intentionally use non-zero exit codes to indicate findings (not failures), and their stdout/stderr contains the valuable diagnostic information users need to see.
Requested Fix
Instead of hiding stdout/stderr when exit code ≠ 0, codex-rs should:
- Always preserve and display stdout/stderr output regardless of exit code
- Clearly indicate the exit code alongside the output (e.g., "Command exited with code 1:")
- Let users and the AI model see the full diagnostic information to make informed decisions
This would eliminate the need for the || true workaround and provide much better user experience when working with development tools that use non-zero exit codes to indicate findings (linters, compilers, test runners, etc.).
Additional Context
- This issue affects the usability of codex-rs with many common development tools
- The
|| trueworkaround is functional but shouldn't be necessary - Users expect to see detailed error output to understand what needs to be fixed
- Both codex-cli and codex-rs implement similar command execution patterns, suggesting this is an architectural decision that affects both CLIs
- The TypeScript codebase contains explicit documentation about exit code handling, indicating this behavior is intentional but problematic for developer tools
- Common affected tools include: flake8, eslint, pytest, jest, cargo check, go vet, and other linters/analyzers that use exit codes to signal findings
Related Files (Likely)
Based on repository structure and source code analysis, the relevant files include:
codex-rs (Rust implementation):
codex-rs/core/src/codex.rs- Containshandle_container_exec_with_paramsfunction that processes container.exec tool callscodex-rs/core/src/exec.rs- Command execution logic and process spawning- Shell tool execution handlers and sandbox implementations
codex-cli (TypeScript implementation with same issue):
codex-cli/src/utils/agent/sandbox/raw-exec.ts- Coreexec()function with exit code handlingcodex-cli/src/utils/agent/handle-exec-command.ts- Higher-level command execution coordinationcodex-cli/src/utils/agent/agent-loop.ts- Tool dispatch logic that callshandleExecCommand
The TypeScript implementation contains explicit comments about exit code → stderr mapping, and the Rust implementation appears to follow similar patterns for consistency between the two CLIs.
Thank you for considering this improvement to make codex-rs more developer-friendly!
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗