Skip to content

desktop: service stuck at 500 after SQLite "disk I/O error" on resume from sleep #59189

Open

Description

@horaniai

Summary

On Windows, resuming from sleep can make the background service boot fail with SQLiteError: disk I/O error. The failed process keeps running and holds the service port, answering 500 on /api/info and 503 on /api/event indefinitely, so OpenCode Desktop cannot start a healthy service and shows Background service failed to start until the stale process is killed manually. The database itself is intact.

Environment

  • opencode version: 2.1.4 (OpenCode Desktop, bundled opencode-cli.exe 2.1.4-x64)
  • OS: Windows 11 Pro 10.0.26200 (build 26200); WSL2 kernel 6.18.40.1-microsoft-standard-WSL2 (the WSL CLI 2.0.32 was unaffected)
  • Terminal: OpenCode Desktop (no TTY); PowerShell for CLI checks
  • Shell: PowerShell
  • Install/channel: Desktop installer OpenCode 2.1.4, latest channel; bundled CLI staged at %APPDATA%\ai.opencode.desktop\cli\2.1.4-x64\opencode-cli.exe
  • Active plugins: local plugin local-permission-sound (%USERPROFILE%\.config\opencode\plugins\local-permission-sound); MCP server obsidian

Reproduction

  1. Run OpenCode Desktop with the managed background service active.
  2. Put Windows to sleep, then resume a few hours later.
  3. The client starts serve --service ~41 s after wake; the boot fails ~7 s after that.
  4. Reopen or retry the desktop app: Desktop IPC handler failed ... Background service failed to start.
  5. The stale process keeps GET /api/info at 500 (and /api/event at 503) indefinitely.

Expected Behavior

After resume, the service should open SQLite successfully (or retry), report healthy on /api/info, and Desktop should reconnect without manual cleanup.

Actual Behavior

Service log (UTC):

timestamp=2026-10-26T03:14:18.333Z level=INFO run=387fa9fe message="cli starting" version=2.1.4 channel=latest local=false args="[\"serve\",\"--service\"]" role=cli
timestamp=2026-10-26T03:14:25.125Z level=ERROR run=16aa2b94 message="background service boot failed" cause="Cause([Die(SQLiteError: disk I/O error)])" role=server
timestamp=2026-10-26T03:14:25.132Z level=INFO run=16aa2b94 message="Sent HTTP response" http.span=3 role=server http.method=GET http.url=/api/info http.status=500
...
timestamp=2026-10-26T05:48:05.047Z level=INFO run=16aa2b94 message="Sent HTTP response" http.span=0 role=server http.method=GET http.url=/api/info http.status=500

Desktop renderer log:

[2026-10-26 07:48:05.577] [error] (renderer) fatal renderer error {
  error: 'Error: Desktop IPC handler failed\n' +
    ... "Background service failed to start" ...

The process that failed at boot stays alive, owns port 44000, and never recovers.

Additional Context

  • PRAGMA quick_check and PRAGMA integrity_check on a copy of opencode.db (31.7 MB) plus its -wal (10.7 MB) returned ok; the database opened read/write in WAL mode and all 20 tables were readable.
  • 8.8 GB free on C:; no disk/NTFS errors in the System event log; the DB directory is a normal directory owned by the user with Full Control; no reparse point.
  • Wake event: Power-Troubleshooter event 1 at 2026-10-26 05:13:37 local time (asleep since 2026-10-25 20:44:43). The failing service start was 41 s later.
  • Seen once so far, not reproducible on demand; earlier boots on the same database succeeded. Real-time antivirus protection was enabled at the time.
  • Workaround that worked: stop the stale process (port 44000 became free), start the service again; /api/info then returned 200 with {"version":"2.1.4","pid":...,"urls":["http://127.0.0.1:44000", ...]} and no further boot failures.
  • Related: Starting background server... Error: Background service failed to start #57032 (stale service prevents restart), Error: Unexpected error disk I/O error #32571 (disk I/O error, older version).

Activity

  1. opencode-agent commented on Oct 26, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed report and logs. I could reproduce this with the 2.1.4 CLI on Linux. I didn't test the desktop app or Windows, but the CLI uses the same background service code as Desktop.

    Steps, simulating the boot-time SQLite failure:

    1. Start the background service once, then stop it.
    2. Make opencode.db unreadable (I overwrote it with random bytes). opencode service start fails with Background service failed to start, and the log shows background service boot failed with SQLiteError: file is not a database. The failed serve --service process stays running on the service port.
    3. Restore the good database and start again. It still fails with Background service failed to start, and opencode service status reports stopped while the failed process is still alive. Only killing that process recovers, which matches your workaround.

    This still happens on the latest dev (ed74ec8). The script below reproduces it.

    Related:

    Until this is fixed, ending the leftover opencode-cli.exe process (or running opencode service stop) and reopening the app is the workaround.

    Reproduction script (repro.sh)
    #!/usr/bin/env bash
    # Reproduces #59189: a background service whose boot fails with a SQLite error
    # stays alive, keeps the port and answers 500 forever; later starts never recover.
    # Usage: ./repro.sh            (uses `opencode` from PATH)
    #        OC="bun --conditions=browser --preload=.../preload.js .../packages/cli/src/index.ts" ./repro.sh
    set -u
    OC=${OC:-opencode}
    ROOT=$(mktemp -d /tmp/opencode/repro59189.XXXX)
    export HOME=$ROOT/home XDG_DATA_HOME=$ROOT/data XDG_STATE_HOME=$ROOT/state XDG_CONFIG_HOME=$ROOT/config XDG_CACHE_HOME=$ROOT/cache
    mkdir -p "$HOME" && cd "${WORKDIR:-$HOME}"
    PORT=${PORT:-44123}
    $OC --version
    $OC service set port $PORT >/dev/null 2>&1 || true
    
    echo "== 1. start once so the database exists"
    timeout 120 $OC service start; echo "exit=$?"
    curl -s -o /dev/null -w "/api/info -> %{http_code}\n" http://127.0.0.1:$PORT/api/info
    timeout 60 $OC service stop; sleep 5
    DB=$(find "$XDG_DATA_HOME" -name 'opencode*.db' | head -1); echo "db=$DB"
    cp "$DB" "$ROOT/good.db"
    
    echo "== 2. simulate a transient SQLite I/O failure at boot (garbage database file)"
    rm -f "$DB"-wal "$DB"-shm
    head -c 65536 /dev/urandom > "$DB"
    timeout 120 $OC service start; echo "exit=$?"
    sleep 2
    grep -h "boot failed" -r "$XDG_DATA_HOME" "$XDG_STATE_HOME" 2>/dev/null | tail -1
    curl -s -o /dev/null -w "/api/info -> %{http_code}\n" http://127.0.0.1:$PORT/api/info
    pgrep -af "[s]erve --service"
    
    echo "== 3. the cause is gone (database restored); start again"
    cp "$ROOT/good.db" "$DB"
    timeout 120 $OC service start; echo "exit=$?"
    curl -s -o /dev/null -w "/api/info -> %{http_code}\n" http://127.0.0.1:$PORT/api/info
    $OC service status
    echo "== still running failed processes:"
    pgrep -af "[s]erve --service"
    
    echo "== cleanup"
    pkill -f "[s]erve --service" ; true

    Run it: bash repro.sh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions