Skip to content

Windows minion will not stop

When a Windows minion update fails and corrupts the package, minion-cli-win stop may fail at the .env read or agent-API call stage and leave the services running. Because NSSM (the Windows service manager) keeps respawning node.exe, files under node_modules\@geekbeer\minion\ stay locked, and npm uninstall -g @geekbeer/minion also fails.

Starting in v3.43.0, the --force flag bypasses graceful shutdown entirely and force-stops every minion service and process. Run from an elevated PowerShell (Administrator).

Terminal window
minion-cli-win stop --force

It performs the following steps in order:

  1. Rewrite NSSM AppExit to Exit and AppThrottle 0 to disable auto-restart temporarily
  2. sc.exe stop for minion-agent / minion-websockify / minion-cloudflared / minion-vnc
  3. Stop-Process -Force for tvnserver / websockify / cloudflared
  4. Kill every node.exe whose Win32_Process.CommandLine matches a minion script
  5. Restore NSSM AppExit Default Restart so a subsequent minion-cli-win start behaves normally

In-flight chats and workflows are aborted, and the offline heartbeat to HQ (/api/shutdown) is skipped — the HQ dashboard will continue to show the minion as online until the heartbeat timeout fires (tens of seconds to a few minutes).

When stop --force is also unusable (manual procedure)

Section titled “When stop --force is also unusable (manual procedure)”

If the CLI itself will not start, or you are on a version older than v3.43.0, run the equivalent steps manually from an elevated PowerShell.

Terminal window
# 1. Disable NSSM auto-restart, then stop and remove each service
$nssm = "$env:USERPROFILE\.minion\nssm.exe" # vendor build: %APPDATA%\npm\node_modules\@geekbeer\minion\win\vendor\nssm.exe
foreach ($svc in 'minion-agent','minion-websockify','minion-cloudflared','minion-vnc') {
& $nssm set $svc AppExit Default Exit 2>$null
& $nssm set $svc AppThrottle 0 2>$null
sc.exe stop $svc 2>$null
Start-Sleep -Seconds 2
& $nssm remove $svc confirm 2>$null
}
# 2. Remove scheduled tasks
Unregister-ScheduledTask -TaskName MinionWSL -Confirm:$false -ErrorAction SilentlyContinue
Unregister-ScheduledTask -TaskName MinionVNC -Confirm:$false -ErrorAction SilentlyContinue
# 3. Kill remaining helper processes
Stop-Process -Name tvnserver,websockify,cloudflared -Force -ErrorAction SilentlyContinue
# 4. Kill only minion-related node.exe processes (leave unrelated node alone)
Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
Where-Object { $_.CommandLine -match 'minion|@geekbeer\\minion|terminal-server|workflow-runner|routine-runner|wsl-session-server' } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }

The steps above release locks in almost every case. If something is still holding the package files, identify the responsible process:

Terminal window
$pkg = "$env:APPDATA\npm\node_modules\@geekbeer\minion" # global install location
Get-Process | Where-Object { $_.Modules.FileName -like "$pkg\*" } |
Select-Object Id, ProcessName

If you have Sysinternals Handle, it pins down the offender even more reliably:

Terminal window
handle64.exe -nobanner $pkg

Stop the listed PIDs with Stop-Process -Id <PID> -Force. As a last resort, an OS reboot always works — set Set-Service minion-agent -StartupType Disabled before rebooting so the service does not start back up and re-lock the files.

Once services and processes are stopped, reinstall normally.

Terminal window
npm uninstall -g @geekbeer/minion
Remove-Item -Recurse -Force "$env:APPDATA\npm\node_modules\@geekbeer\minion" -ErrorAction SilentlyContinue
npm install -g @geekbeer/minion
minion-cli-win setup

Because stop --force skips graceful shutdown completely, it has the following side effects:

  • In-flight chats, workflows, and terminal sessions are aborted abruptly
  • The offline heartbeat is not sent to HQ, so the dashboard shows the minion as online until heartbeat timeout (tens of seconds to a few minutes)
  • Logs and SQLite writes in flight may be left in a partial state

Continue to use minion-cli-win stop (graceful) for normal operations. --force is an emergency fallback for when graceful stop is broken, not a routine command.