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
@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:
- Never gate local-server readiness / instance bootstrap on an outbound fetch — make the catalog refresh fully asynchronous and serve stale-or-empty data meanwhile.
- Add a short timeout (e.g. 10s) and an offline fallback to the models.dev fetch.
- Lower the
FlocktimeoutMsfor this call site, and on lock timeout continue bootstrap instead of blocking. - 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
- Use a network where HTTPS connections to
models.devhang (silent packet drop). To simulate on any machine: block/blackholemodels.devvia firewall or hosts-to-unreachable-IP. - Delete/expire the local models.dev cache so a fetch is triggered at startup.
- Launch the desktop app → window stays on the loading screen; renderer later crashes with
TypeError: Failed to fetch. - While it hangs, kill the app and relaunch → the new instance waits on the leftover/fresh lock; startup can block up to the 300s
Flocktimeout.
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.