You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Wrapper reports signal-based child termination as exit code 0 #17978
For spawnSync, result.status is null and result.signal is set when the child terminates via signal. That makes an abnormal termination look like a clean exit to supervisors and scripts.
This is related to #17854, #15558, and #2489, but it is a different path. Those issues are about opencode run returning 0 for application-level failures. This issue is specifically about the outer wrapper converting signal-based child termination into 0 before the caller ever sees the real signal.
No issue template was used. Please use one of the three required templates: Bug Report, Feature Request, or Question. The bug report template requires fields like OpenCode version, OS, terminal, and steps to reproduce.
Please edit this issue to address the above within 2 hours, or it will be automatically closed.
This issue might be a duplicate of existing issues. Please check:
Error returns exit code 0 #17854: Also reports exit code 0 returned on errors/abnormal conditions (though that issue covers application-level errors rather than signal-based child termination specifically)
If you believe this was flagged incorrectly, please let a maintainer know.
Thank you for updating the issue! It now includes all the required information — a clear description, steps to reproduce, version, OS, and terminal. The compliance label has been removed.
I opened a PR that fixes this wrapper path as part of the same root cause: #26259
The current wrapper has two related signal bugs:
It uses blocking spawnSync(), so the wrapper cannot forward SIGTERM/SIGINT/SIGHUP while the child is running. If a supervisor kills the wrapper, the real .opencode child can survive and become a PID-1 orphan.
As this issue notes, spawnSync() reports signal exits as status: null with signal set, and the wrapper currently maps that to exit code 0.
The PR switches to async spawn(), forwards standard termination signals to the child, and when the child exits due to a signal, re-raises that signal on the wrapper process instead of converting it to 0.
Activity
github-actions commentedon Mar 17, 2026
This issue doesn't fully meet our contributing guidelines.
What needs to be fixed:
Please edit this issue to address the above within 2 hours, or it will be automatically closed.
This issue might be a duplicate of existing issues. Please check:
If you believe this was flagged incorrectly, please let a maintainer know.
github-actions commentedon Mar 17, 2026
Thank you for updating the issue! It now includes all the required information — a clear description, steps to reproduce, version, OS, and terminal. The compliance label has been removed.
chubes4 commentedon May 8, 2026
I opened a PR that fixes this wrapper path as part of the same root cause: #26259
The current wrapper has two related signal bugs:
spawnSync(), so the wrapper cannot forwardSIGTERM/SIGINT/SIGHUPwhile the child is running. If a supervisor kills the wrapper, the real.opencodechild can survive and become a PID-1 orphan.spawnSync()reports signal exits asstatus: nullwithsignalset, and the wrapper currently maps that to exit code0.The PR switches to async
spawn(), forwards standard termination signals to the child, and when the child exits due to a signal, re-raises that signal on the wrapper process instead of converting it to0.Verification:
8d26c4f6-4e90-459b-a15d-49e76cc0f9dabdc45e95-2ec3-44bf-b50a-c7daee37552eSignals tested:
SIGTERM,SIGINT,SIGHUP.