Skip to content

fix(terminal): name shell-level exit codes 126/127 (Closes #1452) - #1472

Merged
Lexus2016 merged 2 commits into
mainfrom
evolution/issue-1452-exit-code-hints
Jul 28, 2026
Merged

fix(terminal): name shell-level exit codes 126/127 (Closes #1452)#1472
Lexus2016 merged 2 commits into
mainfrom
evolution/issue-1452-exit-code-hints

Conversation

@Lexus2016

Copy link
Copy Markdown
Owner

Child 1 of #1371 (terminal 27.4% failure rate across 673 sessions — the dominant failure signal).

The gap

_interpret_exit_code already explains per-command exit codes (grep 1 = no matches, curl 7 = connection failed) and signal codes (137 = SIGKILL). It said nothing about 126 and 127, because those are not per-command — they are about the invocation. 127 means the shell never found anything to run, whatever the command was, so it falls straight through the per-command table and produced no note at all.

Why these two specifically

The failure is not in the command's logic. Re-running the same string cannot succeed — which is exactly the retry-spiral shape behind the parent issue's numbers. So each note states the cause and what to change:

Code Note
126 found but not executable; check permissions (chmod +x) or whether it is a directory. Re-running unchanged will fail identically.
127 not found; check spelling, or whether the tool is installed and on PATH. Re-running unchanged will fail identically; try which or an absolute path.

Ordering is the risk, and it is tested

The new lookup is a fallback, matched after the per-command table and the signal codes. Tests pin this:

  • grep x f exit 1 still reads "No matches found (not an error)", not a generic shell hint
  • curl exit 7 still reads "Failed to connect to host"
  • sleep exit 137 still reads "SIGKILL"
  • an unknown code still returns None rather than a fabricated explanation

8 new tests, 39 passing in test_terminal_exit_semantics.py, 345 across the terminal suites; ruff clean.

Scope

Deliberately just this. Children 2 (#1453, strategy-switch after 3 consecutive failures) and 3 (#1454, security-scan block directive) are separate — and #1453 in particular needs checking against loop_guard, which already fires on the third consecutive terminal failure today.

Child 1 of #1371 (terminal 27.4% failure rate across 673 sessions).

_interpret_exit_code already explains per-command exit codes (grep 1 = no
matches, curl 7 = connection failed) and signal codes (137 = SIGKILL). It said
nothing about 126 and 127, because those are not per-command: they are about the
INVOCATION. 127 means the shell never found anything to run, whatever the
command was, so it falls through the per-command table and produced no note.

Those two are worth naming precisely because the failure is not in the command's
logic. Re-running the same string cannot succeed, which is the retry-spiral
shape behind the parent issue's numbers. Each note therefore states the cause
AND what to change:

  126 -> found but not executable; check permissions (chmod +x) or whether it is
         a directory. Re-running unchanged will fail identically.
  127 -> not found; check spelling, or whether the tool is installed and on PATH.
         Re-running unchanged will fail identically; try `which` or an absolute
         path.

Ordering matters and is tested: per-command semantics and signal codes are
matched BEFORE this fallback, so `grep x` exit 1 still reads "No matches found"
rather than a generic shell hint, and an unknown code still returns None instead
of a fabricated explanation.

8 new tests; 39 passing in test_terminal_exit_semantics.py; ruff clean.

Closes #1452
@github-actions github-actions Bot added fix Bug or fix security labels Jul 28, 2026
@Lexus2016
Lexus2016 merged commit c2cba7b into main Jul 28, 2026
36 checks passed
@Lexus2016
Lexus2016 deleted the evolution/issue-1452-exit-code-hints branch July 28, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Bug or fix security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant