Skip to content

free tier: FreeUsageLimitError depends on request size — long sessions always fail while new sessions succeed #58751

Closed as duplicate

Description

@resulbegmyradow33-sys

Description

On the free tier (opencode/* models, no Go subscription, $0 Console balance) FreeUsageLimitError is not a simple "daily messages exhausted" state. It depends on the size of the individual request: a session with a large assembled context is rejected on every turn, while a new session on the same account succeeds in the same minute.

2026-10-25 00:06 local (UTC+8), same account, same machine, same model opencode/deepseek-v4.1-flash-free:

  • ses_08a6d445… (July session: 985 user messages, 14,966 assistant messages, 45.9M input tokens, last successful request 126k tokens on 23 Oct 18:21, assembled context now ≈447k tokens, estimated from the 1.79 MB context payload) → Free usage limit reached…, idle outcome failed
  • ses_e9155f04… (new session, 23k tokens per request) → normal answer 18 seconds later

So the quota is not "this account is blocked". The same account can still make small requests while a large session is refused.

Environment

  • opencode 2.1.4, desktop app (bundled CLI), macOS (Darwin 25.6.0, arm64)
  • Model: opencode/deepseek-v4.1-flash-free, agent build
  • Shell: zsh; using the desktop app, not the TUI
  • Plugins: 3 local plugins configured under ~/.config/opencode/plugins/*.ts; all three fail to load in 2.1.4 (Plugin must export a default definition), so effectively none are active
  • Free tier only: no OpenCode Go subscription, no paid balance

Reproduction

  1. Use only free opencode/* models.
  2. Let one session grow until its assembled request context is several hundred thousand tokens. Mine has 99 context items / 1.79 MB (GET /api/session/{id}/context), and auto-compaction keeps it around that size.
  3. Send any prompt to that session → Free usage limit reached. Connect a provider or subscribe to OpenCode Go to keep going, or switch models. Stored as an assistant message with error type provider.free-limit, followed by an idle message with outcome: "failed".
  4. In the same minute, create a new session and send a prompt → it succeeds.

Expected Behavior

Either the request succeeds, or the error says what was exhausted and when it resets. The outcome should not depend on how much history a session carries.

Actual Behavior

The large session is rejected every time; small requests pass. Inside a single session the result flips with context size:

time (local) assembled ctx (tokens) result
00:06:41 23,163 ok
00:39:28 167,591 fail
00:39:57 auto-compaction runs —
00:40:25 49,408 ok
00:50:06 82,107 fail
00:50:12 83,049 ok

The last two rows are 6 seconds apart at the same size, which looks like a rolling bucket at its boundary rather than a hard per-request cap.

Usage history from the same machine (session_message, providerID=opencode):

day requests input tokens cache read free-limit errors
20 Oct 494 1,804,867 47.7M 0
21 Oct 251 1,020,301 24.7M 0
23 Oct 148 361,336 14.8M 0
24 Oct 3 0 0 3 (blocked all day)
25 Oct 133 728,646 12.8M 18

20–21 Oct: heavy use, zero errors. 24 Oct: blocked from the first attempt. 25 Oct 00:06: works again, then ~730k input tokens in 45 minutes exhausts it. Something changed on the service side around 21–23 Oct, and the remaining allowance now behaves like a small bucket that refills over minutes/hours.

Additional Context

Client mapping: a QuotaExceeded error whose body contains FreeUsageLimitError becomes provider.free-limit with the message above. That is different from the "You've used today's free messages, they reset at …" copy, and I never see a reset time in this path.

How the numbers above were read (no instrumentation, just local state):

sqlite3 ~/.local/share/opencode/opencode.db "
select datetime(time_created/1000,'unixepoch','localtime') t,
       json_extract(data,'$.tokens.input') + coalesce(json_extract(data,'$.tokens.cache.read'),0) ctx,
       case when data like '%provider.free-limit%' then 'FAIL' else 'OK' end st
from session_message
where type='assistant' and json_extract(data,'\$.model.providerID')='opencode'
order by time_created desc limit 10;"

Related issues, and how this one differs:

Questions:

  1. Is the free allowance documented anywhere (tokens or requests, per day or rolling window)?
  2. Is rejecting a request because of its assembled context size intentional?
  3. Can the client expose the remaining allowance and reset time in this error path, as [FEATURE]:Show exact free usage limit reset time #52894 asks?

Activity

  1. opencode-agent commented on Oct 24, 2026

    @opencode-agent
    Contributor

    Thanks for the detailed measurements, @resulbegmyradow33-sys. They show clearly that on the free tier, long sessions with a large context hit Free usage limit reached while small new sessions still go through.

    How the free allowance is counted, how big it is and when it resets are decided by the OpenCode service, not by the app. Billing and account support isn't handled in GitHub issues, so please email help@anoma.ly with the details: the timestamps, the model, and the table of requests and tokens per day you gathered. If you've already emailed, the team will get to it, especially now that we've seen it here. Please keep email addresses, account details and anything related to payment out of this public issue and put them in the email instead.

    Your questions about the app itself are already tracked here:

    In the meantime, starting a new session or compacting the long one keeps each request small, which in your tests let requests through.

    The bot will close this issue in 1 day.

  2. resulbegmyradow33-sys commented on Oct 24, 2026

    @resulbegmyradow33-sys
    Author

    Thanks. One clarification, because I think this is not an account-specific billing question:

    The same account, same model and same minute produce both outcomes:

    • 00:06:23 — the long session (large assembled context) → Free usage limit reached
    • 00:06:41 — a new session, 23k tokens → normal answer

    And inside the new session the result flips with context size alone: 167k tokens failed, then auto-compaction brought it to 49k and it passed; later 82k failed and 83k passed six seconds apart. Nothing about the account changed between those pairs.

    So the observable behavior is: whether a request is accepted depends on the size of that request. That is reproducible from local state without any Console access, which is why I filed it here rather than as billing support.

    The question I still need an answer to is #2 above: is the per-request context-size check intentional? If yes, documenting it in #57540 would settle it and I'll close this myself. If no, the numbers in the report are enough to reproduce it.

  3. opencode-agent commented on Oct 25, 2026

    @opencode-agent
    Contributor

    Closing this now, since billing and account support happens by email rather than in GitHub issues. Thanks again for the detailed measurements, @resulbegmyradow33-sys.

    For anything still open about how your free allowance is counted or about your account, please email help@anoma.ly. Please put any account details in the email, not here.

    The app-side requests are still tracked in #57540 (documenting how free-tier usage is counted) and #52894 (showing the reset time when the limit is hit).

  4. neriousy commented on Nov 4, 2026

    @neriousy
    Member

    Thanks for the report, and sorry for the trouble!

    We're tracking all free-tier quota and limit problems in one place: the pinned issue #59387. Please read it first. Most of these reports are fixed by updating to the latest OpenCode v2 (Desktop v1 users can download it from https://opencode.ai/v2/docs).

    If you're on the latest v2 and still hitting this, please add your details there: OpenCode version, OS, model, and the exact error or reset time shown. Keeping everything in one thread helps us find the cause faster.

    Closing as a duplicate of #59387.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions