What happened?
Running gemini --resume to restore a previous session crashes the CLI with the following critical error:
ERROR ioctl(2) failed, EBADF
Full stack trace:
UnixTerminal.resize (/node_modules/@lydell/node-pty/unixTerminal.js:243:13)
_ShellExecutionService.resizePty (bundle/chunk-FLP3MI27.js:359821:30)
commitHookEffectListMount (bundle/chunk-DQXMK6DN.js:5266:30)
...
What did you expect to happen?
--resume should restore the session normally without crashing due to a PTY resize operation.
Root Cause Analysis
The error handler in ShellExecutionService.resizePty() currently only catches two recoverable error types:
ESRCH — the target process has already exited, causing ioctl to fail
- Windows-specific error —
"Cannot resize a pty that has already exited"
In the resume scenario, however, the PTY file descriptor from the previous session has already been closed when the original process exited. On resume, ExecutionLifecycleService.attachExecution re-attaches the execution, causing isPtyActive() to return true, but the underlying PTY fd is stale. The ptyProcess.resize() call then invokes ioctl(fd, TIOCSWINSZ, ...) on the invalid fd, which returns EBADF (bad file descriptor) rather than ESRCH.
Since EBADF is not handled by the existing catch block, the exception propagates upward and crashes the process.
Proposed Fix
Add EBADF to the list of safely ignorable error codes in the resizePty() catch block, treating it the same as ESRCH.
Location: packages/core/src/services/shellExecutionService.ts around line 1554
const isEsrch = err.code === 'ESRCH';
+ const isEbadf = err.code === 'EBADF';
const isWindowsPtyError = err.message?.includes(
- if (isEsrch || isWindowsPtyError) {
+ if (isEsrch || isEbadf || isWindowsPtyError) {
Client information
- Platform: Linux
- Version: Gemini CLI (development branch)
- Repro command:
gemini --resume
Login information
No response
Anything else we need to know?
No response
What happened?
Running
gemini --resumeto restore a previous session crashes the CLI with the following critical error:Full stack trace:
What did you expect to happen?
--resumeshould restore the session normally without crashing due to a PTY resize operation.Root Cause Analysis
The error handler in
ShellExecutionService.resizePty()currently only catches two recoverable error types:ESRCH— the target process has already exited, causingioctlto fail"Cannot resize a pty that has already exited"In the resume scenario, however, the PTY file descriptor from the previous session has already been closed when the original process exited. On resume,
ExecutionLifecycleService.attachExecutionre-attaches the execution, causingisPtyActive()to returntrue, but the underlying PTY fd is stale. TheptyProcess.resize()call then invokesioctl(fd, TIOCSWINSZ, ...)on the invalid fd, which returnsEBADF(bad file descriptor) rather thanESRCH.Since
EBADFis not handled by the existing catch block, the exception propagates upward and crashes the process.Proposed Fix
Add
EBADFto the list of safely ignorable error codes in theresizePty()catch block, treating it the same asESRCH.Location:
packages/core/src/services/shellExecutionService.tsaround line 1554Client information
gemini --resumeLogin information
No response
Anything else we need to know?
No response