Skip to content

Bug Report: After a hard crash in PowerShell, OpenCode database lock persists until OpenCode runs successfully from CMD #38246

Description

@XYRen-FXTech

Description

Bug Report: After a hard crash in PowerShell, OpenCode database lock persists until OpenCode runs successfully from CMD

Environment

Item Detail
OS Windows 10 Pro 22H2 (Build 19045)
Terminal Windows Terminal
Shell PowerShell 7.1 (primary), Git Bash 5.2.37 / MSYS2 (secondary)
OpenCode versions 1.18.3 → upgraded to 1.18.4 → downgraded back to 1.18.3
Plugins opencode-smart-approval v0.5.0
AI Provider DeepSeek (deepseek-v4-pro)
Working directory Contains CJK (Chinese) characters in path
Install method npm install -g opencode-ai

Symptoms

  1. TUI crashes instantly — window flashes, alternate screen buffer activates briefly (escape sequences visible), then exits silently with exit code 0. No error message, no stack trace.

  2. Mouse escape sequences flood the terminal after crash — the TUI's mouse capture mode remains active and raw ANSI sequences are written to the terminal.

  3. opencode run "message" initially works, but subsequently also exits silently (exit code 0, zero output).

  4. opencode session list, opencode stats, opencode debug info — all exit code 0 with zero bytes on stdout and stderr.

  5. opencode --version, opencode debug paths, opencode debug startup — these continue to work. They are the only commands that don't require database access.

  6. opencode serve dies immediately (no log output produced).

  7. Restarting the terminal does NOT fix the problem. Only rebooting the machine temporarily resolves it.

  8. The critical clue: Launching OpenCode from cmd.exe works. After a successful cmd.exe session exits normally, PowerShell also starts working again — in the same PowerShell tab that previously crashed, without restarting the shell process.

Full Debugging Journey

Step 1: Initial suspicion — mouse tracking corruption

Checked logs at %USERPROFILE%\.local\share\opencode\log\opencode.log. All level=ERROR entries were error=Aborted stack=undefined, which turned out to be user-initiated Ctrl+C interrupts, not crashes. The actual crash produced no log entry at all — characteristic of a Bun-level hard crash (SIGSEGV/SIGILL).

Found issue #24288 about Windows mouse escape sequence leakage. Verified that OPENCODE_DISABLE_MOUSE is an officially recognized env var by extracting strings from the 173MB opencode.exe binary:

useMouse:!lf.OPENCODE_DISABLE_MOUSE&&U.config.mouse

Set OPENCODE_DISABLE_MOUSE=1 as a Windows user environment variable. Mouse flooding stopped, but TUI still crashed. This ruled out mouse tracking as the primary cause.

Step 2: Database integrity check

Headless mode (opencode run "message") worked fine. This meant the core engine and AI provider were functional. The crash was specific to TUI and server mode initialization.

Ran SQLite integrity check on the database (57MB) via Python:

conn = sqlite3.connect(db_path)
cursor.execute('PRAGMA integrity_check')
# Result: ok
cursor.execute('PRAGMA wal_checkpoint(TRUNCATE)')
# Result: disk I/O error

Key finding: The main database file was intact (integrity_check: ok), but the WAL (Write-Ahead Log) was corrupted. The wal_checkpoint consistently failed with disk I/O error.

Step 3: The database lock discovery

Attempted to VACUUM the database into a repaired copy. The VACUUM succeeded on a temp copy (57.7MB → 57.5MB, integrity verified), but could not replace the original file:

PermissionError: [WinError 5] Access denied

Further investigation revealed:

  • del /F opencode.db → "Access is denied"
  • ren opencode.db opencode.db.old → "Access is denied"
  • Writing a NEW file to the same directory → Works fine
  • PowerShell [IO.File]::Open with FileShare.None → Succeeds (file CAN be opened for I/O)

Conclusion: The file is not locked by another process in the traditional sense. It's a zombie file handle — the process that held it open has crashed, but Windows has not released the handle. This is a kernel-level orphaned lock that survives process termination but not reboots.

Step 4: Workaround with OPENCODE_DB env var

Used the OPENCODE_DB env var (also found in the binary strings) to point OpenCode to the repaired database at a different filename:

OPENCODE_DB=%USERPROFILE%\.local\share\opencode\opencode_fixed.db

opencode run worked again. But TUI and serve still crashed. This proved database access was necessary but not sufficient for TUI recovery.

Step 5: Binary reinstall

The upgrade log showed an EPERM error during the 1.18.3→1.18.4 upgrade:

Error: EPERM: operation not permitted, unlink '...opencode-windows-x64\bin\opencode.exe'

The old binary could not be replaced because it was in use. A subsequent downgrade may have encountered the same issue in reverse. Performed a clean reinstall:

npm uninstall -g opencode-ai
npm install -g opencode-ai@1.18.3

After reinstall, opencode run worked consistently. But TUI still crashed in PowerShell.

Step 6: The PowerShell vs CMD discovery

At this point, a hypothesis emerged: PowerShell's PTY/process model might be preventing proper cleanup of the zombie file handle.

Tested from cmd.exe:

set OPENCODE_DISABLE_MOUSE=1
set OPENCODE_DB=%USERPROFILE%\.local\share\opencode\opencode_fixed.db
opencode --pure

cmd.exe TUI launched successfully. After exiting normally:

  1. The old opencode.db file lock was released (could now delete it)
  2. Replaced old DB with repaired copy
  3. Removed OPENCODE_DB env var
  4. PowerShell 7.1 TUI now works — in the same tab that was crashing minutes earlier, without any shell restart

Step 7: Restoration and verification

All workaround measures were reverted:

  • OPENCODE_DB env var removed
  • .bashrc OPENCODE_DB export removed
  • Repaired database placed at standard location (opencode.db)
  • OPENCODE_DISABLE_MOUSE=1 kept as preventive measure

OpenCode now works normally in all terminals (PowerShell 7.1, CMD, Git Bash).

Root Cause Analysis (Three-Layer Model)

Layer 1: The initial crash

The first crash that triggered the entire chain was likely a Bun segfault on Windows. Evidence:

The v1.18.4 upgrade had an EPERM error (could not unlink old opencode.exe), which may have left the binary in a partially-corrupted state, contributing to instability.

Layer 2: Database corruption cascade

When OpenCode hard-crashed:

  1. The SQLite WAL file contained un-checkpointed writes → WAL corruption
  2. The opencode.exe process died without calling CloseHandle() on the database file
  3. Windows marked the file handle as a zombie — the process is dead but the kernel hasn't released the lock
  4. Every subsequent OpenCode launch attempted to open the database → hit the zombie lock → silently exited

Layer 3: PowerShell 7.1's process model amplifies the problem

This is the most interesting finding and the unreported aspect of this bug:

PowerShell 7.1 appears to use a different console/PTY process architecture than cmd.exe. When a child process (opencode.exe / Bun) hard-crashes under PowerShell:

  • The zombie file handle seems to be retained within PowerShell's process tree
  • Even restarting the terminal tab doesn't fully release it (the handle may persist in the Windows console session)
  • cmd.exe uses a simpler, more isolated process model that is not affected

When OpenCode runs successfully from cmd.exe and exits normally:

  1. SQLite performs automatic WAL recovery on the database
  2. The normal exit path calls proper cleanup (CloseHandle, win32FlushInputBuffer)
  3. The zombie handle is somehow forced-released by the kernel
  4. All terminals can now access the database normally

This is why "just run it from CMD once" fixes everything.

Workaround / Fix

Immediate fix (no reboot needed)

:: Open a CMD terminal (not PowerShell)
set OPENCODE_DISABLE_MOUSE=1
opencode --pure
:: Type /exit to quit normally
:: Now PowerShell should work again

Full repair (if the above doesn't suffice)

:: 1. Remove corrupted WAL
del %USERPROFILE%\.local\share\opencode\opencode.db-wal
del %USERPROFILE%\.local\share\opencode\opencode.db-shm

:: 2. Reinstall OpenCode
npm uninstall -g opencode-ai
npm install -g opencode-ai

:: 3. Launch from CMD once
set OPENCODE_DISABLE_MOUSE=1
opencode --pure
:: Type /exit

Preventive measure

Set OPENCODE_DISABLE_MOUSE=1 as a persistent Windows user environment variable to reduce the probability of future TUI-related crashes.

Other observations

  • opencode web mode works even when TUI is broken — useful as a fallback
  • opencode run "message" (headless) works more reliably than TUI — can be used for quick testing
  • opencode serve mode also crashes silently, possibly related to #38220 (Bun HTTP server on Windows)
  • Database was 57MB with 11 sessions, 316 messages, 1319 parts — all data preserved after repair
  • CJK characters in working directory path did not cause any issues

Diagnostic Commands Reference

# Check OpenCode paths
opencode debug paths

# Check database integrity (Python)
python -c "
import sqlite3
conn = sqlite3.connect(r'%USERPROFILE%\.local\share\opencode\opencode.db')
c = conn.cursor()
c.execute('PRAGMA integrity_check')
print(c.fetchone())
c.execute('PRAGMA wal_checkpoint(TRUNCATE)')
print(c.fetchall())
conn.close()
"

# Check if database is locked (PowerShell)
$f = "$env:USERPROFILE\.local\share\opencode\opencode.db"
try {
    $fs = [IO.File]::Open($f, [IO.FileMode]::Open, [IO.FileAccess]::ReadWrite, [IO.FileShare]::None)
    $fs.Close(); Write-Host 'Not locked'
} catch { Write-Host "Locked: $_" }

# Find OPENCODE_* env vars supported by the binary
strings opencode.exe | grep -oP 'OPENCODE_[A-Z_]+' | sort -u

Related Issues

Issue Relation
#24288 Windows mouse escape sequence leak — likely contributed to initial crash
#8785 Bun segfault on Windows — likely root cause of the first crash
#35847 Bun panic (Illegal instruction) on Windows 11
#34940 Terminal corruption after /exit
#38220 Windows serve/web HTTP not accepting connections under Bun
#37416 Mouse text selection crashes TUI on Windows 11

Hard-to-reproduce note

This bug is difficult to reproduce on demand because it requires:

  1. A Bun hard crash during normal OpenCode use (itself non-deterministic on Windows)
  2. The crash must occur in PowerShell 7.1 specifically
  3. The resulting zombie handle state is invisible to normal diagnostic tools

However, the diagnostic signature is clear: if OpenCode works from CMD but not from PowerShell, this bug is the cause. The fix is immediate and reliable.

Plugins

No response

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions