anomalyco / anomalyco/opencode

opencode run hangs indefinitely when the usage quota is exhausted, instead of reporting the error it already has

Open
#40,747 3 comments 0 reactions 1 assignee View on GitHub

@rekram1-node is already working on this.

Since Aug 5, 2026.

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

Description

Summary

When a model's usage quota is exhausted, opencode run never exits and never
reports the reason
. The process hangs indefinitely with no output on stdout and
nothing but a banner on stderr — even though the error is known internally within
~170 ms and written to opencode's own log file.

Any non-interactive use (scripts, CI, an app shelling out to the CLI) therefore
hangs until an external timeout kills it, and the caller has no way to tell an
exhausted quota from a slow model.

The interactive TUI handles this case properly, so this looks specific to the
non-interactive run path.

Version

opencode 1.17.11, Linux x86_64.

Reproduction

With a subscription whose quota is exhausted:

$ timeout 90 opencode run --model opencode-go/<any-model> "say hi"
rc=124            # killed by `timeout`, not by opencode
stdout: 0 bytes
stderr: 34 bytes  # only: ESC[0m "> build · <model>" ESC[0m

Same result with --format json (stdout and stderr both 0 bytes), and at
120 s and 300 s ceilings. The process never terminates on its own.

It knows almost immediately

--print-logs --log-level DEBUG on the same run:

11:42:33.920 INFO  run=… message=stream providerID=opencode-go modelID=<model> …
11:42:34.091 ERROR run=… message="stream error" … error.error="AI_APICallError: Monthly usage limit reached. Resets in N days. …"
11:42:36.448 ERROR run=… message="stream error" … small=true agent=title … error.error="AI_RetryError: Failed after 3 attempts. Last error: Monthly usage limit reached. …"

171 ms from stream start to a fully-formed error. It reaches the log file and
then goes nowhere else, and the process continues to hang.

(The second line is the title-generation agent hitting the same wall after its
own retries — possibly relevant to why the run never unwinds.)

Expected

opencode run should exit non-zero and print the provider's error. With
--format json, emitting the existing error envelope on stdout would be enough:

{"type":"error","error":{"type":"GoUsageLimitError","message":"Monthly usage limit reached. …"}}

That is the shape errors already take on that stream, so a caller could parse it
with no new contract.

Actual

Exit code: none — the process must be killed externally.
stdout: empty.
stderr: a decorative banner only.

Why it matters

A CLI that hangs forever is worse than one that fails: a wrapper cannot
distinguish "out of quota" from "model is slow" and has to wait out its full
timeout budget before giving up, on every subsequent call too. Exiting non-zero
with the message that is already in hand would make this a two-line failure
instead.


Identifiers (workspace, session, run ids) redacted from the log excerpts above.

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.