anomalyco / anomalyco/opencode

[desktop] Startup blocked up to 5 min by models.dev fetch under global Flock when network silently drops packets; UI never loads

Open
#47,328 1 comment 0 reactions 1 assignee View on GitHub

@rekram1-node is already working on this.

Since Sep 4, 2026.

Dominant language
TypeScript
Stars
209k
Forks
27.5k
PR merge metrics
PR metrics pending

Description

Description

On Windows, the desktop app repeatedly failed to open: the window stayed stuck on the loading screen and the renderer eventually crashed with fatal renderer error: TypeError: Failed to fetch. Restarting the app did not help and often made it worse.

Root cause (verified against the bundled server code and live reproduction): during startup, when the models.dev catalog cache is missing/stale, ModelsDev.populate() acquires a global file lock (Flock, at <state>/locks/<hash>.lock) and then performs a synchronous HTTPS fetch to models.dev. Flock is configured with timeoutMs: 300_000 (5 minutes) and staleMs: 60_000. On networks where outbound packets are silently dropped (mainland China without a working proxy — connections hang for the full ~21s Windows TCP SYN retransmission window per attempt), the lock-holding process stays alive and keeps its heartbeat fresh while the fetch hangs. Every other server instance then blocks inside startup waiting on the lock, for up to 5 minutes per launch. While blocked, the local HTTP server does not answer the renderer's initial requests (/session, /config, /provider, …), so the UI never renders and the renderer eventually dies with Failed to fetch.

Killing the app mid-fetch makes the next launches even worse: the lock directory is left behind (I found an orphaned lock whose meta.json pointed to a long-dead PID), and rapid relaunches pile up lock contention.

Impact: app is completely unusable behind unstable/filtered networks, with no error message indicating the real cause and no offline fallback.

Workaround (verified): set OPENCODE_DISABLE_MODELS_FETCH=1. Startup then skips the fetch/lock path entirely: all 12 project instances finished bootstrap in ~10s with zero models.dev log entries.

Suggested fixes:

  1. Never gate local-server readiness / instance bootstrap on an outbound fetch — make the catalog refresh fully asynchronous and serve stale-or-empty data meanwhile.
  2. Add a short timeout (e.g. 10s) and an offline fallback to the models.dev fetch.
  3. Lower the Flock timeoutMs for this call site, and on lock timeout continue bootstrap instead of blocking.
  4. Surface a visible "working offline / catalog unavailable" state in the UI instead of an infinite loading screen.
Plugins

Default desktop install (one local plugin file in ~/.config/opencode/plugins, unchanged since long before the issue; ruled out by bisection).

OpenCode version

OpenCode Desktop 1.18.27 (Windows x64, packaged; Electron 42.3.3 / Node 24.15.0).

Steps to reproduce
  1. Use a network where HTTPS connections to models.dev hang (silent packet drop). To simulate on any machine: block/blackhole models.dev via firewall or hosts-to-unreachable-IP.
  2. Delete/expire the local models.dev cache so a fetch is triggered at startup.
  3. Launch the desktop app → window stays on the loading screen; renderer later crashes with TypeError: Failed to fetch.
  4. While it hangs, kill the app and relaunch → the new instance waits on the leftover/fresh lock; startup can block up to the 300s Flock timeout.
Screenshot and/or share link

N/A — logs attached instead. Key excerpts below.

Server bootstrap timings (from ~/.local/share/opencode/log/opencode.log)

Time from bootstrapping directory=... to init per server run:

Date bootstrap → init
Jun 12 – Sep 2 (30+ runs) 0.7 – 4.8 s (always healthy)
Sep 4 12:34 95.3 s
Sep 4 12:38 78.3 s
Sep 4 12:40 21.9 s
Sep 4 12:43 140.1 s
Sep 4 18:33 113.0 s
Sep 4 19:22 164 s
Sep 4 19:08 / 19:11 never completed (app killed after 100+s)
Sep 4 23:40, with OPENCODE_DISABLE_MODELS_FETCH=1 10.1 s for all 12 instances, 0 models.dev calls

Failure-day durations cluster around multiples of ~21s, the signature of Windows TCP connect timeouts (3s+6s+12s SYN retransmissions) — i.e. repeated hanging outbound connection attempts.

Orphaned lock left by a killed process

%APPDATA%\ai.opencode.desktop\opencode\locks\8bc5da6c...lock\meta.json:

{"token":"ac4513ce-0810-4d1c-9fd2-ea292da4a44b","pid":18216,"hostname":"<redacted>","createdAt":"2026-09-04T11:25:25.676Z"}

The lock was acquired 0.8s after the run's first instance finished init (i.e. right when the catalog populate ran), the process was killed mid-fetch, and the lock with a frozen heartbeat was left behind.

Live reproduction with the bundled server

I extracted the server bundle (out/main/chunks/node-*.js) from app.asar and ran it with the app's own Electron Node runtime, replicating sidecar.js:

Run Condition Result
A fresh state dir, request /config?directory=F:\wordtest 12.3 s (lock wait + slow fetch)
A then /session?directory=C:\Users\<me> hung > 200 s
B warm catalog cache 0.73 s
C desktop-identical env + orphaned stale lock present 0.68 s — stale lock was broken and cleaned up correctly

Stale-lock breaking works; the blocker is a live lock holder stuck in the hanging fetch (fresh heartbeat, up to the 300s timeout).

Operating System

Windows 11 (10.0.26200), x64

Terminal

N/A — desktop app (Electron sidecar server)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.