Fix remote VM session failing with exec: trap: not found before SSH - #740
Merged
sbertix merged 1 commit intoJul 29, 2026
Merged
Conversation
…table Ghostty runs a surface command as `bash -c "exec -l <command>"`, so the command must begin with an executable. When local zmx is unavailable, buildRemoteCommand returned the bare reconnect loop, which opens with a `trap` builtin; `exec -l trap ...` then tried to run `trap` as a program and the remote SSH surface died with `exec: trap: not found` before ssh started. Wrap the fallback loop in `/bin/sh -c`, mirroring the inner shell the zmx-wrapped path already uses.
sbertix
enabled auto-merge (squash)
July 29, 2026 22:41
sbertix
deleted the
sbertix/gh-737-remote-vm-session-fails-before-ssh-bash
branch
July 29, 2026 22:51
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.
Closes #737
Summary
Opening a remote VM session over SSH failed before SSH even started, with
bash: line 0: exec: trap: not found, whenever local zmx was unavailable (unbundled or over budget).On macOS, Ghostty runs a surface
.shellcommand stringvas/usr/bin/login -flp <user> /bin/bash --noprofile --norc -c "exec -l <v>", sovmust begin with an executable.ZmxAttach.buildRemoteCommandreturned the bareSSHReconnectLoop.script(...)in the no-local-zmx fallback, and that script opens with thetrapshell builtin. Prefixed with Ghostty'sexec -l, it becameexec -l trap 'exit 130' INT; ..., soexectried to runtrapas a program and the surface died with exit 127 before ssh ran. The zmx-wrapped path was unaffected because it already leads with the quoted zmx executable path.The fallback now wraps the loop as
/bin/sh -c '<loop>'(no leadingexec, which would break the same way), so Ghostty producesexec -l /bin/sh -c '<loop>', leading with a real executable and running the loop in a fresh shell. This mirrors the inner/bin/sh -cthe zmx-wrapped path already uses; that path is unchanged.Type of change
ready)How was this tested?
Reproduced the failure and verified the fix at the shell level (
exec -l trap ...exits 127; the/bin/sh -c-wrapped form exits 0). AddedbareReconnectLoopSurvivesGhosttyExecLoginWrapping, which parses the real fallback withsh -n, runs the exactbash -c "exec -l …"shape on a benign wrapped loop, and pins the regression with a negative control on the unwrapped loop. Updated the existing fallback assertion to expect the wrapping.make checkpasses (format + lint)make testpassesChecklist
Closes #above.ready.