Skip to content

<leader>x (:xall) leaves terminal job running → E948; cleanup only fires on QuitPre #2

@chiro-hiro

Description

@chiro-hiro

Severity: high · Category: bug
Location: plugin/keymaps.vim — line 8 (nnoremap <leader>x :xall<CR>) interacting with QuitPre autocmd at lines 36-39

What's wrong

The terminal-cleanup logic (s:CloseTerminalsOnExit) is hooked exclusively to the QuitPre autocommand. :xall (the command bound to <leader>x) does NOT fire QuitPre, so the cleanup never executes and the running terminal job blocks the quit. A user who edits a file, opens a terminal with <leader>t, then presses <leader>x to save-and-quit gets E948: Job still running and Vim stays open with the change half-applied. By contrast <leader>q (:confirm qall) and :q DO fire QuitPre and work correctly. This also directly contradicts the design intent stated in the surrounding comment and in CLAUDE.md, which claims terminals auto-close "when Vim exits."

Evidence

Tested with vim 9.0 against the actual file. :xall does not trigger QuitPre:
autocmd QuitPre * let g:qp+=1 ... xall -> result quitpre_fired=0 while Vim still exited (exit=0).
Full repro using the real s:OpenTerminal flow (edit a file, below new + term_start sleep, modify buffer, run :xall): result xall_error=Vim(xall):E948: Job still running, Vim left open with 2 windows.
The cleanup is only registered for QuitPre:
augroup ivim_terminal_cleanup
autocmd QuitPre * call s:CloseTerminalsOnExit()
augroup END
There is no VimLeavePre / ExitPre / other handler covering :xall (or :wqall).

Suggested fix

Either (a) add :call s:CloseTerminals() into the <leader>x mapping path, e.g. nnoremap <leader>x :xall<CR> -> a small function that wipes terminals then runs :xall; or (b) make the cleanup fire on a broader event. Simplest robust fix: change the mapping to call a wrapper, e.g.
function! s:SaveQuitAll() abort
call s:CloseTerminals()
xall
endfunction
nnoremap x :call SaveQuitAll()
Note QuitPre still handles the plain :q/<leader>q cases, so keep that too. (Consider the same wrapper if :wqall is ever added.)

Related documentation

CLAUDE.md — line 170 (Terminal section)

The doc states terminals auto-close "when Vim exits — QuitPre autocommand gated on the last non-terminal window ... and :qall never trips E947." While :qall/:confirm qall are correctly handled, <leader>x (:xall) bypasses QuitPre entirely and fails with E948 (see the keymaps.vim finding). The blanket "when Vim exits" claim is inaccurate for the save-and-quit-all path.

Fix: After fixing the keymaps.vim bug, update this line to reflect that <leader>x/:xall cleans terminals via an explicit wrapper (not via QuitPre), or generalize the statement once the fix covers all quit-all variants.


Filed from an automated multi-agent source review (2026-05-29); finding adversarially verified at high confidence. Line numbers reflect the audit-fixes-2026-05 working tree.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions