Skip to content

opencode run intermittently hangs during init — no session created, no output, no error (~56% failure rate observed) #38723

Closed as not planned

Description

@VinylStage

Summary

opencode run intermittently hangs before creating a session. When it happens the process stays alive but produces zero stdout, emits no error, and never progresses past message=init in the log. The only way out is an external timeout.

The failure is intermittent, not deterministic. Over 61 invocations in one day I measured a 44% success rate (27/61), with hourly rates swinging between 8% and 77%. A later controlled 40-run trial in a "good" window produced 40/40 successes, so the failure window and the healthy window can be minutes apart with no configuration change in between.

Read-only subcommands (--version, agent list, models) always respond instantly, even while run is hanging.

Environment

opencode 1.18.4 (also reproduced on 1.17.11)
Install npm install -g opencode-ai (nvm-managed prefix, no sudo)
OS macOS 26.5.2 (build 25F84), Darwin 25.5.0, arm64
Hardware Apple M4 Pro, 48 GB unified memory
Node v24.17.0 (nvm)
npm 12.0.0
Provider Ollama 0.32.3 via @ai-sdk/openai-compatible at http://127.0.0.1:11434/v1

Relevant config (~/.config/opencode/opencode.jsonc), though the issue reproduces with no user config at all:

{
  "$schema": "https://opencode.ai/config.json",
  "share": "disabled",
  "autoupdate": true,
  "model": "ollama/qwen3-coder:30b",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama (Local)",
      "options": { "baseURL": "http://127.0.0.1:11434/v1", "timeout": 1800000 }
    }
  }
}

Steps to reproduce

Reproduction is probabilistic. There is no known trigger; the same command succeeds or hangs depending on when it is run.

mkdir -p /tmp/oc-repro && cd /tmp/oc-repro
timeout 120 opencode run "answer in one word: what is 1+1?"
echo "exit=$?"   # 0 when it works (~19s), 124 when it hangs

Run this repeatedly with a gap between attempts. In failure windows it hangs on most attempts; in healthy windows it succeeds every time in ~19 seconds.

Do not judge by exit code alone. Because stdout is buffered until completion, a hung run and a slow run look identical from the shell. The reliable discriminator is whether a session was created:

grep -c 'message=created' ~/.local/share/opencode/log/opencode.log

Observed behaviour

Log signature

A successful run progresses through:

init → created → event → loop → shell → init → booting → stream → loop → exiting loop → disposing instance

A hung run stops dead at the first init:

timestamp=... message="creating instance" directory=/tmp/oc-repro
timestamp=... message=fromDirectory directory=/tmp/oc-repro
timestamp=... message=bootstrapping directory=/tmp/oc-repro
timestamp=... message=loading path=/Users/<user>/.config/opencode/config.json
timestamp=... message=loading path=/Users/<user>/.config/opencode/opencode.json
timestamp=... message=loading path=/Users/<user>/.config/opencode/opencode.jsonc
timestamp=... message="all LSPs are disabled"
timestamp=... message="all formatters are disabled"
timestamp=... message=init
<nothing further — process stays alive until killed>

No created, no stream, no error, no warning at --log-level DEBUG.

Timing is bimodal, not a slowdown

Across 40 controlled runs, every successful run completed in 18–19 seconds (min 18, max 19). Hung runs never complete — observed up to 900s. There is no middle ground: a run either finishes in ~19s or does not progress at all.

Network evidence — connection to models.dev held open with no progress

During a hung run, lsof showed an ESTABLISHED connection to 172.67.69.147:443 held for the entire 30-second sampling window while the run made no progress:

$ lsof -nP -a -p <pid> -i
COMMAND     PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
opencode. 14462 vinyl   15u  IPv4 ...        0t0  TCP 192.168.x.x:50476->172.67.69.147:443 (ESTABLISHED)

172.67.69.147 resolves as one of the A records for models.dev:

$ dig +short models.dev
104.26.9.108
104.26.8.108
172.67.69.147

(registry.npmjs.org resolves to a different range, 104.16.x.x, so this is models.dev specifically.)

Meanwhile the host itself was perfectly reachable from the same machine at the same time:

$ curl -s -o /dev/null -w "namelookup=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} total=%{time_total}\n" https://models.dev/
namelookup=0.001497 connect=0.140799 tls=0.287761 total=1.107086   # HTTP 200

System resolver was also instant (socket.getaddrinfo("models.dev", 443) → 0.00s).

So the remote endpoint was healthy while opencode sat on an established connection to it without progressing.

A second, different hang shape

Not every hang looks the same. In other hung runs, lsof showed the process holding no sockets at all — not to models.dev, and not even to the local Ollama endpoint on 127.0.0.1:11434:

t=2  PID=14286 connections=[none]
t=4  PID=14286 connections=[none]
...
t=30 PID=14286 connections=[none]

This suggests there may be more than one stall path, or a stall that occurs before any socket is opened. I could not determine which.

OPENCODE_OFFLINE=1 does not suppress the models.dev request

In a controlled, interleaved 40-run trial (20 with OPENCODE_OFFLINE=1, 20 without, alternating, fixed 45s gap between runs), connections to models.dev were sampled during every run:

Arm Runs Sessions created models.dev connection observed
OPENCODE_OFFLINE=1 20 20/20 4
control 20 20/20 4

Identical. The environment variable did not reduce contact with models.dev.

Note this sampling is a lower bound: connections were polled every 2s, so short-lived requests during fast (~19s) runs are frequently missed. A zero should be read as "not observed", not "did not happen". The signal that matters here is that both arms show the same rate.

Frequency data

Uncontrolled observations, 2026-07-24 — 61 opencode run invocations, classified by whether a session was created:

Hour (UTC) Sessions created / attempts
01–09 10/13 (77%)
10 4/9 (44%)
11–12 1/13 (8%)
13 0/4 (0%)
14–15 12/22 (55%)
Total 27/61 (44%)

Controlled trial, 15:26–16:08 UTC — 40 runs, alternating arms, fixed 45s gap: 40/40 succeeded, all in 18–19s. This window began roughly 10 minutes after a stretch of 6 consecutive failures, with no configuration change in between.

What was ruled out

Every one of these was tested; the hang reproduced after each:

Hypothesis How it was ruled out
User config Rolled back through three prior states, then removed opencode.jsonc entirely
Project-level config Reproduced both with and without a project opencode.jsonc
Corrupted install Clean reinstall to 1.18.4 with postinstall scripts explicitly allowed
Plugins Reproduced with --pure
Local state / DB Deleted opencode.db, -shm, -wal; recreated (56 tables) and still hangs
OS-level resource leak Full machine restart
Binary integrity / Gatekeeper Mach-O arm64, no com.apple.quarantine (only com.apple.provenance)
Ollama unhealthy Direct /api/generate call answered in 1.7s while run was hanging
DNS / network path getaddrinfo 0.00s; curl https://models.dev/ → HTTP 200 in 1.1s
Disk / memory 69 GiB free, ~50% memory free
Auto-update in flight --version instant; no update activity in logs

One incidental finding while reinstalling: with npm's allowScripts policy active, npm install -g opencode-ai@latest completes but silently skips the postinstall script, leaving a broken install whose --version prints "reinstall opencode-ai without the --ignore-scripts flag". Given autoupdate: true is the default, a self-update under that policy could leave users in a broken state. This is separate from the hang (the hang persisted after a correct reinstall) but may be worth handling.

What I think is happening

Stated as a hypothesis, not a conclusion — I do not have enough evidence to confirm it:

opencode appears to contact models.dev during startup, and at least one code path can wait on that request indefinitely with no timeout and no error surfaced. The observed ESTABLISHED-but-idle connection is consistent with this. What I cannot explain is the second hang shape where no sockets exist at all.

If startup does depend on a network fetch, a bounded timeout with a fallback to cached data (and a log line on failure) would turn a silent indefinite hang into a recoverable, diagnosable condition.

What would help

  • Is a models.dev (or other remote) fetch on the run startup path, and does it have a timeout?
  • Is there a supported way to make startup fully offline? OPENCODE_OFFLINE=1 did not appear to affect the request in my testing.
  • Would you accept a log line at the point where init blocks, so this failure is diagnosable without lsof?

I have raw per-run data (timestamps, exit codes, elapsed, session-created flags, connection samples) for all 101 runs and can attach it if useful.

Activity

  1. github-actions commented on Jul 24, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    Your investigation (ESTABLISHED connection to 172.67.69.147 = models.dev, no progress, no error, no timeout) points to the same underlying issue described in those reports. The intermittency you observed — healthy windows vs. failure windows — is consistent with models.dev itself being slow or partially degraded rather than fully unreachable, which would explain why curl succeeds (fast path) while the opencode fetch stalls on a slower/different connection.

    The second hang shape (no sockets at all) may be a separate code path, so it could be worth noting as an addition to one of those existing issues rather than a duplicate.

  2. JazielGuerrero commented on Jul 30, 2026

    @JazielGuerrero

    I'm seeing this as well (opencode run hangs). In my case it hangs 100% of the time. I'm running OpenCode inside a Daytona sandbox through their Go SDK.

    After debugging, I traced it to this line:

    const piped = process.stdin.isTTY ? undefined : await Bun.stdin.text()

    Since the execution environment is not a TTY and its stdin behaves differently than expected, this line blocks indefinitely:

    await Bun.stdin.text()

    A simple way to check if you're hitting the same issue is to run:

    opencode run

    If stdin isn't blocking, you should immediately see:

    You must provide a message or a command
    

    In my environment, it hangs instead and never reaches that validation.

    As a workaround, I pipe the prompt into stdin so EOF is delivered correctly. For example:

    echo "Awesome prompt" | opencode run

    or

    opencode run < prompt_file.txt
  3. zealchou commented on Aug 4, 2026

    @zealchou

    Third independent confirmation, on a platform not yet represented here — and, more usefully, a deterministic reproduction. The report notes "Reproduction is probabilistic. There is no known trigger", so this may help whoever picks it up.

    @JazielGuerrero's diagnosis (await Bun.stdin.text() in cli/cmd/run.ts) matches everything we observed. The missing piece is why it looks intermittent: it isn't. It is fully determined by whether the launching environment hands opencode run a stdin that ever reaches EOF.

    Deterministic repro

    # A: stdin is a pipe whose write end is never closed → hangs, every time
    mkfifo /tmp/oc.fifo
    sleep 300 > /tmp/oc.fifo &
    timeout 45 opencode run "answer in one word: what is 1+1?" < /tmp/oc.fifo
    echo "exit=$?"        # 124, zero stdout, log stops at message=init
    
    # B: same command, stdin redirected to /dev/null → succeeds, every time
    timeout 45 opencode run "answer in one word: what is 1+1?" < /dev/null
    echo "exit=$?"        # 0

    Measured on our machine: A hung 5/5, B succeeded 10/10.

    This also explains the observations in the original report that looked mysterious:

    • "Intermittent, 8%–77% by hour" — not time-dependent. Different launchers give different stdin. A shell with a TTY works; a background job, CI step, orchestrator, or anything using spawn with the default stdio: 'pipe' and no explicit stdin.end() does not.
    • "40/40 successes in a good window" — that window was a launcher whose stdin reached EOF.
    • "Killing the stuck process makes the next one work" — killing the process tree also releases the pipe's write end.
    • Read-only subcommands respond instantly — they never reach the stdin read.
    • We also saw this with opencode run --attach against a healthy opencode serve: the server's /session list showed no new session at all, because the client blocks before it sends anything.

    Environment

    opencode 1.18.10
    Install npm install -g opencode-ai
    OS / arch Linux 6.17, aarch64 (NVIDIA GB10)
    Provider local vLLM via @ai-sdk/openai-compatible on 127.0.0.1

    Different OS, different arch, different provider from the two cases already in this thread — the trigger is the same.

    Workaround

    Append < /dev/null to every non-interactive opencode run invocation. That took our batch pipeline from intermittent indefinite hangs to 6/6 first-try successes.

    Suggested fix

    Only read stdin when there is a reason to. Two options that would both have avoided this for us:

    1. Skip the read entirely when a prompt was already supplied as an argument — there is nothing to merge stdin into.
    2. Otherwise, treat a non-TTY stdin as best-effort: read with a short timeout and continue with what arrived, rather than blocking on EOF forever.

    Either way, a bounded read would turn "hangs forever with no output and no error" into a normal run.

  4. emilaiev commented on Aug 4, 2026

    @emilaiev

    Fourth platform — and a second, distinct blocking resource: not stdin, but the TCP connect to opencode.ai during startup.

    Environment

    opencode 1.18.13
    Install npm install -g opencode-ai
    OS Linux 6.6.87.2 (WSL2 on Windows 11), x86_64
    Provider opencode-go (cloud) — model API confirmed healthy during freeze windows via direct calls

    Same symptom: opencode run alive, zero model output, no session created, healthy windows minutes away from frozen ones with no config change.

    Deterministic A/B repro (run today on 1.18.13)

    Stdin pinned to /dev/null in both arms, so @zealchou's variable is eliminated:

    # Arm A: silently drop opencode.ai (Cloudflare, 172.65.90.20–23)
    sudo iptables -I OUTPUT -d 172.65.90.20 -j DROP   # (+ .21 .22 .23)
    timeout 75 opencode run "reply with one word: ok" < /dev/null
    # → exit 124, no output. Mid-run `ss -tnp`:
    #   SYN-SENT 172.65.90.20:443, .21:443, .22:443, .23:443 — 6 sockets, zero bytes
    
    # Arm B: remove the drop, same command
    sudo iptables -D OUTPUT -d 172.65.90.20 -j DROP   # (+ .21 .22 .23)
    timeout 90 opencode run "reply with one word: ok" < /dev/null
    # → answers "ok" in 5.1s

    The only difference between the arms is the packet drop.

    Controls — what it is not

    • Not models.dev: same DROP technique against models.dev, with the models cache deleted to force a fetch — runs start in ~1s. The bot's pattern-match is the right bug class, but the wrong host, at least on 1.18.13/Linux.
    • Not IPv6 fallback: this box has no IPv6 route; v6 attempts fail in ms with ENETUNREACH and Happy Eyeballs prefers IPv4. The hang is IPv4 SYN-SENT.
    • Not stdin (in this arm): stdin was /dev/null both times, and the blocked process had six open TCP connects — a process blocked in Bun.stdin.text() would show none. @zealchou's stdin case is real (we adopted < /dev/null everywhere as hardening), but it cannot explain SYN-SENT sockets.

    Why it looks intermittent

    opencode.ai is intermittently slow from a given network path, not down. Connect attempts sit in kernel SYN retransmit for minutes, which produces the minutes-wide good/bad windows the original report measured by hour.

    Suggested fix

    Bound the startup sync to opencode.ai: a connect timeout plus an overall budget (e.g. 5s / 15s), then continue degraded and create the session anyway. A silent remote should cost seconds, not the run. Together with @zealchou's bounded stdin read, the two fixes would cover every hang shape reported in this thread.

    Local mitigation meanwhile

    A supervisor that kills a run producing zero output at 60s and re-dials after 90s (freeze windows are minutes-wide, so the retry usually lands in a healthy one) took our headless batch from silent indefinite hangs to 12/12 starts.

  5. VinylStage commented on Aug 5, 2026

    @VinylStage
    Author

    Fourth independent confirmation, and I can now retract my own original diagnosis.

    I filed this report. My investigation pointed at models.dev (an ESTABLISHED-but-idle TCP connection during init), and the duplicate-detection bot above followed that lead. That was the wrong trail. @JazielGuerrero and @zealchou have the actual cause, and I reproduced their determinism test on a platform not yet in this thread.

    Repro on macOS / arm64

    Same two arms as @zealchou, unchanged:

    # A — stdin is a pipe whose write end is never closed
    mkfifo oc.fifo
    sleep 120 > oc.fifo &
    timeout 45 opencode run "answer in one word: what is 1+1?" < oc.fifo
    
    # B — same command, stdin redirected to /dev/null
    timeout 45 opencode run "answer in one word: what is 1+1?" < /dev/null
    Arm Result
    A 5/5 hung. exit=124 every time, 45s wall clock, 0 bytes on stdout
    B 6/6 succeeded. exit=0, 2–37s (first run slower — model load)

    Not probabilistic. Deterministic in both directions.

    opencode 1.18.5
    OS / arch macOS 26.6, arm64 (Apple silicon)
    Provider local Ollama (qwen3-coder:30b) over the OpenAI-compatible endpoint

    Worth noting the version: @zealchou measured 1.18.10, I measured 1.18.5, on a different OS, different arch, and a different local-inference stack. Same trigger, so this is not recent and not platform-specific.

    Why my original "intermittent, 8–77% by hour" numbers fit this

    My report described a failure rate that swung wildly by time of day. Measured then:

    Hour block Success
    01–09 10/13 (77%)
    10 4/9 (44%)
    11–12 1/13 (8%)
    13 0/4 (0%)
    14–15 12/22 (55%)
    Total 27/61 (44%)

    I treated the swing as a property of the environment. Under the stdin explanation it is a property of how each batch was launched, and one observation I could never explain now falls out cleanly:

    After 6 consecutive hangs, I built a controlled 40-run alternating A/B experiment to test an unrelated hypothesis (an offline env var). It ran 40/40 success over 42 minutes, starting ~10 minutes after that failure streak, with no configuration change whatsoever. Both arms were 20/20, so the experiment was inconclusive by its own declared criterion — I recorded it as "cannot discriminate."

    The thing that changed was not the config. It was that the 40 runs were driven by a purpose-built shell harness rather than the launcher used before it. Under @zealchou's explanation, that harness handed opencode run a stdin that reached EOF, so every run completed.

    Caveat, stated plainly: I did not record the stdin state of each run at the time, so I cannot retroactively prove which launcher each of those 61 runs used. This is consistency with the hypothesis, not independent proof of it. The 5/5 vs 6/6 above is the proof; this section is just the anomaly that no longer needs a special explanation.

    Workaround

    < /dev/null on every non-interactive invocation. Confirmed here.

    On the suggested fix

    @zealchou's option 1 — skip the stdin read entirely when a prompt was already passed as an argument — would have prevented every failure I logged. In all 61 of my runs the prompt was supplied as an argument, so nothing was ever going to be merged in from stdin; the read was pure cost.

    I would add one thing regardless of which option is chosen: the failure mode itself is worth fixing separately. No output, no error, no session, no log line past message=init, and an exit only when something external kills it. That is what turned a one-line stdin bug into a multi-day investigation that produced a wrong root cause. A bounded read that logged stdin: waiting for EOF even once would have ended it in minutes.

    Happy to run further tests on macOS/arm64 if that helps.

  6. postoso commented on Aug 27, 2026

    @postoso

    Still reproduces on 1.18.23 (brew tap, macOS): opencode run with an inherited open stdin hangs indefinitely at startup, timeout kills it with no output and no session created; the same invocation with < /dev/null succeeds immediately. The redirect remains a reliable workaround.

  7. z80690 commented on Aug 31, 2026

    @z80690

    Same issue on Windows. OpenCode 1.18.25 (also reproduced on 1.18.23 and 1.18.16): opencode run --pure --agent build -m opencode/mimo-v2.5-free "say OK" hangs at the first init in the log — ~62 seconds of zero output/error, no session created, then "cleanup prune=7.days" and the process stays alive until killed. Reproduced in both the project dir and a clean empty dir. TUI mode works fine; only headless run hangs. Also confirmed api.opencode.ai reachable (HTTP 200), 0 credentials in auth. This blocks all headless/CI usage. Happy to run any diagnostic you suggest.

  8. postoso commented on Sep 1, 2026

    @postoso

    The TUI-works / headless-run-hangs split you are seeing is the tell, and it matches what I traced on macOS.

    opencode run reads stdin to EOF before it does anything else. The TUI path never does this, which is why only run hangs. If the process inherits an stdin that is open and never closes, which is the normal case for a CI runner, a background job, or an agent harness, it waits there forever. Nothing is logged past init because nothing has happened yet, and no session is created, so there is no session id to recover from afterwards.

    The one-token check: add a stdin redirect and run the identical command.

    opencode run --pure --agent build -m opencode/mimo-v2.5-free "say OK" < /dev/null

    On 1.18.25 here that is the whole difference. Without the redirect: exit 124 under timeout, zero bytes on stdout, empty stderr. With it: clean run. I measured 5 of 5 hangs without and 5 of 5 successes with when I first chased this, and it still reproduces the same way on 1.18.25 today.

    If that fixes it for you, then it is not intermittent and it is not network, it is just whether the calling shell happened to leave stdin open. That also explains why it looked flaky across environments rather than consistently broken.

  9. Vijayapardhu commented on Oct 21, 2026

    @Vijayapardhu

    Adding a deterministic cause for this one — it may not be intermittent after all.

    Repro on Windows 11 / OpenCode 2.1.2: when the working directory is a git work-tree with a very large untracked file set, opencode run hangs before creating a session, with zero stdout and no error — exactly the symptom described here.

    The discriminator appears to be the size of the untracked set, not a flaky window:

    files time
    git ls-files --others --exclude-standard 1,126,526 84.67s
    same, with a .gitignore 5,325 0.36s
    opencode run before — never completes
    opencode run after — 7.1s

    A child git.exe running

    git --git-dir="~/.local/share/opencode/snapshot/global/<hash>" --work-tree="<cwd>" \
        update-index --add --remove --replace -z --stdin
    

    stays resident at ~99% CPU (>207s CPU observed, still running after 5+ minutes) and holds index.lock in the snapshot repo. No provider request is ever made, and no session / session_v2 row is written — which is consistent with "no session created" in this report.

    The working directory in my case was $HOME (a git work-tree with no commits and no .gitignore), where the legacy Windows junctions re-expose AppData as nine extra trees and push the untracked set to ~1.13M paths.

    So one concrete way to test the 44%-success-rate theory: measure git ls-files --others --exclude-standard | wc -l in the cwd of the failing and succeeding runs. If the failures correlate with a large untracked count, the trigger is the snapshot indexer, not a network or plugin window.

    Worth also noting that read-only subcommands (opencode models, opencode debug config) returning instantly while run hangs is consistent with this — they never reach the snapshot indexer.

    Filed as #57841 with the full reproduction, since it covers the Windows-specific mechanics. Related: #48657.

  10. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    Thanks for the very thorough investigation and the timing and network data.

    This report is about OpenCode v1 (1.18.4 / 1.17.11, the opencode-ai npm package). v1 now only gets fixes for critical bugs such as data loss, security problems, or breakage with no workaround. An intermittent hang that a retry gets past is unlikely to be fixed there.

    We'd encourage you to try v2 (the @opencode/cli npm package, which provides the opencode command). The startup code there is a separate implementation. Its models.dev catalog fetch stops after 10 seconds, can fall back to a cached catalog, and logs Failed to fetch models.dev when it fails, rather than waiting forever on the connection. That matches the timeout, fallback and log line you suggested. We haven't confirmed that it fixes your exact case, though, especially the second hang shape where the process has no sockets open.

    If this also happens on v2, or you believe it is critical for v1, please reply here with the v2 version and a log from a hung run, and we'll take another look.

  11. opencodejr commented on Oct 29, 2026

    @opencodejr
    Contributor

    Closing this as not planned. It's an intermittent opencode run hang on OpenCode v1 (1.18.4 / 1.17.11), and v1 only gets fixes for critical bugs. Retrying gets past this hang, so it doesn't count as critical. We didn't hear back after the last comment.

    Thanks again for the detailed investigation. If you see the same hang on v2 (@opencode/cli), please open a new issue with the v2 version and a log from a hung run, and link back to #38723.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions