/codex: an unguarded mktemp still hands codex an empty stderr path (fail closed like the other skills)
Version: gstack 1.87.3.0 (85b8c038), macOS (Darwin 25.5), zsh 5.9 and bash 3.2, codex-cli 0.153.4
1.64.0.0 fixed the BSD mktemp suffix bug (#2091, #2370). Thank you. One path to the same symptom is still open: the /codex sections never check whether mktemp succeeded.
codex/sections/review-mode.md.tmpl TMPERR=$(mktemp "$TMP_ROOT/codex-err-XXXXXX")
_PROMPT_FILE=$(mktemp "$TMP_ROOT/codex-prompt-XXXXXX")
codex/sections/consult-mode.md.tmpl TMPRESP=$(mktemp "$TMP_ROOT/codex-resp-XXXXXX")
TMPERR=$(mktemp "$TMP_ROOT/codex-err-XXXXXX")
codex/sections/challenge-mode.md.tmpl TMPERR=${TMPERR:-$(mktemp "$TMP_ROOT/codex-err-XXXXXX")}
When mktemp fails, the variable is empty. That happens when TMP_ROOT is unwritable or full, or when a sandbox sets a TMPDIR that doesn't exist. 2>"$TMPERR" then fails before codex starts. Review mode prints [codex exit 1] no stderr captured (review-mode.md:61), which reads as a Codex failure, exactly as #2091 did.
Repro. zsh and bash give the same result:
$ TMP_ROOT=/nonexistent
$ TMPERR=$(mktemp "$TMP_ROOT/codex-err-XXXXXX")
mktemp: mkstemp failed on /nonexistent/codex-err-Jv5ShC: No such file or directory
$ true 2>"$TMPERR"; echo "exit=$?"
zsh:1: no such file or directory:
exit=1
Other skills already fail closed here:
- plan-design-review, autoplan (the ceo, eng, dx and design phases) and design-consultation use
_OUTSIDE_TMP=$(mktemp -d …) || exit 1. - ship (the PR body scan) uses
PR_BODY_FILE=$(mktemp) || { echo "ERROR: mktemp failed — …" >&2; exit 1; }.
Proposal: give the five /codex mktemp calls the same guard, for example:
TMPERR=$(mktemp "$TMP_ROOT/codex-err-XXXXXX") || { echo "ERROR: mktemp failed in TMP_ROOT=$TMP_ROOT; not running codex without its temp file" >&2; exit 1; }
Then pin it next to test/mktemp-portability.test.ts: every $(mktemp assignment in codex/sections/*.tmpl must be followed by ||.
We carried this guard as a local patch on 1.60.1.0, together with the X-run fix. After upgrading to 1.87.3.0, the guard is the only part upstream lacks.
Source: garrytan/gstack