Skip to content

[Bug] opencode-go returns AI_APICallError: Insufficient Balance on deepseek-v4-pro and deepseek-v4-flash despite active Go subscription with 50% usage remaining #27598

Closed

Description

@r3vs

Bug Report

Provider: opencode-go
Endpoint: POST https://opencode.ai/zen/go/v1/chat/completions
Affected models: deepseek-v4-pro, deepseek-v4-flash
Go subscription status: Active, ~50% usage remaining


Error from logs

ERROR service=llm providerID=opencode-go modelID=deepseek-v4-pro
  error={"error":{"name":"AI_APICallError","url":"https://opencode.ai/zen/go/v1/chat/completions", ...}}
  stack=AI_APICallError: Insufficient Balance

Same error occurs for deepseek-v4-flash (which also consumes Go subscription quota — it is not free via opencode-go).


Key observation

Provider Model Consumes quota Result
opencode-go deepseek-v4-pro Go subscription ❌ Insufficient Balance
opencode-go deepseek-v4-flash Go subscription ❌ Insufficient Balance
opencode (Zen, non-Go) deepseek-v4-flash-free Free ✅ Works

Note: deepseek-v4-flash-free is only free when accessed via providerID=opencode (Zen). Via opencode-go, deepseek-v4-flash consumes Go subscription quota. Both paid Go models fail while the Zen free model works — this confirms the issue is with the opencode-go backend's upstream DeepSeek account balance, not the user's personal quota or API key.

Multiple API keys have been tried. /connect was redone from scratch. The problem persists across all keys.


Steps to reproduce

  1. Active OpenCode Go subscription with usage remaining
  2. Configure providerID=opencode-go, modelID=deepseek-v4-pro (or deepseek-v4-flash)
  3. Send any request
  4. Receive AI_APICallError: Insufficient Balance from https://opencode.ai/zen/go/v1/chat/completions

Expected behavior

Requests to opencode-go with remaining subscription quota should succeed.


Notes

Activity

  1. github-actions commented on May 14, 2026

    @github-actions
    Contributor

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

    Please review these issues to see if your problem is already tracked. If it is, consider adding a comment there instead to consolidate information.

  2. joaomj commented on May 14, 2026

    @joaomj

    i am facing the same problem.

  3. CamiloFernando commented on May 14, 2026

    @CamiloFernando

    Reproducing "Agent completed without producing any output" in --format json mode

    Adding a reproduction for the empty-response failure that differs from the balance/credits angle in the OP.


    Environment

    • opencode 1.14.50
    • Provider: opencode-go
    • Models affected: mimo-v2.5, deepseek-v4-pro, glm-5.1 (all reasoning models)
    • Works: native TUI (opencode run)
    • Breaks: --format json mode (used by any programmatic consumer, e.g. opendesign)

    Root cause: trailing SSE event after [DONE]

    The opencode-go backend sends a non-standard SSE event after the stream terminates:

    data: {"id":"...","choices":[{"index":0,"delta":{"content":"ok"},"finish_reason":"stop"}]}
    
    data: [DONE]
    
    data: {"choices":[],"cost":"0"}    ← this event should not exist after DONE
    

    Reproduce with:

    curl -s -N -X POST https://opencode.ai/zen/go/v1/chat/completions \
      -H "Authorization: Bearer <your-key>" \
      -H "Content-Type: application/json" \
      -d '{"model":"opencode-go/mimo-v2.5","messages":[{"role":"user","content":"Reply with only: ok"}],"stream":true,"max_tokens":200}'

    What breaks

    opencode's --format json subprocess mode parses the stream sequentially. When it processes {"choices":[],...} after [DONE], it sees an empty choices array and overwrites the assembled message with empty content. The session loop never emits exiting loop and never sends HTTP 200 back to the caller.

    Evidence from opencode's own log (~/.local/share/opencode/log/):

    # Content IS streaming (bus events fire normally):
    INFO service=bus type=message.part.delta publishing   ← repeated many times
    INFO service=bus type=message.part.updated publishing
    INFO service=bus type=message.updated publishing
    INFO service=bus type=session.status publishing
    # ← process exits here. No "exiting loop", no "http.status=200"
    

    Compare to a working session (Claude provider), which shows:

    INFO service=session.prompt step=1 exiting loop
    INFO service=bus type=session.idle publishing
    INFO http.method=POST http.url=/session/.../message http.status=200 Sent HTTP response
    

    A programmatic consumer (opendesign) catches this as:

    [test:agent] OpenCode → no_text (exit 0)
    

    — opencode exited 0 but getText() was empty (the content was assembled internally but never flushed to the stdout JSON stream).


    TUI vs --format json

    The TUI mode either ignores post-DONE events or doesn't re-parse them. --format json mode re-processes every SSE event sequentially, so it gets tripped by the trailing one. This is why opencode run in a terminal works perfectly while any programmatic consumer fails.


    Suggested fix

    On the backend: stop emitting data: {"choices":[],"cost":"0"} after data: [DONE]. If cost reporting is needed, include it in the final non-empty choices event or in a custom header.

    On the client side: ignore any SSE event that arrives after data: [DONE] has been seen.

  4. r3vs commented on May 15, 2026

    @r3vs
    Author

    Im closing this it's working since yesterday night.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions