Repository navigation
Python: Report repeated native exit codes in persistent PowerShell sessions - #9658
Open
Aditya Kumar (Aditya-XR) wants to merge 1 commit into
Open
Aditya Kumar (Aditya-XR) wants to merge 1 commit into
Aditya Kumar (Aditya-XR) wants to merge 1 commit into
Conversation
…ssions A persistent PowerShell session reported exit code 0 when a native command failed with the same code as the previous one. The exit-code check compared $LASTEXITCODE by value, which does not change when the code repeats, and $? reflects Invoke-Expression rather than the native command. Compare by reference instead: PowerShell stores a newly boxed int on every native exit, so the variable holds a different object exactly when the command ran a native process. $LASTEXITCODE is still never written.
Aditya Kumar (Aditya-XR)
requested review from
SergeyMenshykh,
Tao Chen (TaoChenOSU),
Eduard van Valkenburg (eavanvalkenburg),
Giles Odigwe (giles17),
Jose Alvarez (jpalvarezl),
Evan Mattson (moonbox3),
Roger Barreto (rogerbarreto),
sophia-ramsey and
westey (westey-m)
as code owners
October 23, 2026 18:12
Aditya Kumar (Aditya-XR)
deployed
to
github-app-auth
October 23, 2026 18:12 — with
GitHub Actions
Active
Aditya Kumar (Aditya-XR)
deployed
to
github-app-auth
October 23, 2026 18:12 — with
GitHub Actions
Active
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation & Context
In a persistent PowerShell session,
LocalShellToolreportsexit_code=0when a native command fails with the same code as the previous native command.ShellSession._build_scriptdecides whether the command ran a native process by checking whether$LASTEXITCODEchanged ($LASTEXITCODE -ne $__af_last). A repeated code doesn't change the value, and the$?fallback can't catch it, because$?reflectsInvoke-Expression, which succeeded. An agent that reruns a failing test command is told that the second run passed. This affects anyone using the tool on Windows, where PowerShell is the default shell, and anyone runningpwshin persistent mode elsewhere.Description & Review Guide
What are the major changes?
One line in the PowerShell branch of
_build_script: the check compares references instead of values.PowerShell stores a newly boxed int in
$LASTEXITCODEevery time a native process exits, even when the code is the same, so the variable holds a different object exactly when this command ran a native process (or assigned the variable itself).$__af_lastkeeps the reference taken before the command. Like Python: reset $LASTEXITCODE per command in persistent PowerShell sessions #8206, this never writes$LASTEXITCODE, so the user's own commands can still read the previous code. The comments above the check now explain why it compares references.There is also a regression test,
test_persistent_powershell_reports_repeated_native_exit_code. It runs a Python process that exits with 3 three times and expects 3 each time, then checks that a cmdlet-only command reports 0 and that$LASTEXITCODEstill reads back 3. Without the fix it fails withAssertionError: attempt 2 reported rc 0. Liketest_persistent_powershell_returns_formatted_object_output, it is gated on PowerShell being installed rather than onsys.platform == "win32", and it usessys.executableas the native command, so it should also run in theubuntu-latestCI job.What is the impact of these changes?
Repeated native failures now report their own exit code. For the repro in the linked issue (Windows 11, PowerShell 7.6.6):
The other exit-code paths are unchanged. I compared before and after on PowerShell 7.6.6 and Windows PowerShell 5.1 for cmdlet-only commands in a fresh session (where
$LASTEXITCODEis$null) and after a native failure, reading$LASTEXITCODEback, a cmdlet error after a native failure, a native command followed by a cmdlet, several native commands in one command (the last one decides),$global:LASTEXITCODE = 9,throw, and table-formatted output. The only differences were the repeated-code cases, which now report the right code. Bash sessions and stateless mode are untouched.What do you want reviewers to focus on?
Whether relying on reference identity is acceptable. I checked it on PowerShell 7.6.6 and Windows PowerShell 5.1 for exit codes 0, 1, 2, 3, 127, 255 and -1, and both store a new boxed int on every native exit. The alternatives I considered either write
$LASTEXITCODEbefore the command, which Python: reset $LASTEXITCODE per command in persistent PowerShell sessions #8206 avoided so the user's commands can still read it, or need a different way to run the command thanInvoke-Expression.Related Issue
Fixes #9657
This is a one-line correction to the exit-code check added in #8206, so I opened it together with the issue.
AI Assistance
AI assistance details: I used AI coding assistants (Claude Code and Antigravity) to help find the bug and to draft the fix, the test, the linked issue and this description. I did the final review myself: I read and understood every change, checked the repro and test results, and made the final decisions on what to submit.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.