Repository navigation
Description
Description
Fresh-state standalone runs reject a live model while the initial catalog refresh is pending.
Summary
A fresh run --standalone --model opencode/glm-5.3-flash-free can fail with provider.no-route while the startup catalog request is still pending. The bundled catalog lacks this live model. Delaying only that request reproduces the failure; a fresh run against the normal endpoint returned OK.
OpenCode version
Latest npm @opencode/cli: 2.0.31, installed in an isolated prefix. Source inspected: release tag v2.0.31 and current dev at ed772f5009755b5262805a7ba07e66e1417f140a; the relevant catalog and model-resolution paths match. Runtime reproduction used the published binary, not a source build.
Plugins
No user plugins or credentials; fresh HOME/XDG roots and project config disabled.
Steps to reproduce
Install the stated release into a temporary prefix, set OC to its opencode executable, and run this Python script. It serves an unchanged copy of the current catalog with a three-second response delay using the supported process-level URL override. It uses fresh state, runs no tools, and removes its temporary state. Requires Python 3 and curl.
W=$(mktemp -d)
npm install --prefix "$W/oc" @opencode/cli@2.0.31
export OC="$W/oc/node_modules/.bin/opencode"
export TMPDIR="$W"
# Save the following Python as repro.py, then run: python3 repro.pyimport http.server, json, os, pathlib, subprocess, tempfile, threading, time
binary = pathlib.Path(os.environ["OC"]).resolve()
body = subprocess.check_output(["curl", "-fsSL", "https://models.opencode.ai/api.json"])
assert "glm-5.3-flash-free" in json.loads(body)["opencode"]["models"]
work = pathlib.Path(tempfile.mkdtemp(prefix="opencode-catalog-", dir=os.environ["TMPDIR"]))
class Catalog(http.server.BaseHTTPRequestHandler):
def do_GET(self):
time.sleep(3)
try:
self.send_response(200)
self.end_headers()
self.wfile.write(body)
except (BrokenPipeError, ConnectionResetError):
pass
def log_message(self, *args):
pass
server = http.server.ThreadingHTTPServer(("127.0.0.1", 0), Catalog)
threading.Thread(target=server.serve_forever, daemon=True).start()
env = {"PATH": os.environ["PATH"], "HOME": str(work), "OPENCODE_DISABLE_PROJECT_CONFIG": "1"}
for name, suffix in [("CONFIG", ".config"), ("DATA", ".local/share"), ("CACHE", ".cache"), ("STATE", ".local/state")]:
env["XDG_" + name + "_HOME"] = str(work / suffix)
env["OPENCODE_MODELS_URL"] = "http://127.0.0.1:" + str(server.server_port)
try:
result = subprocess.run([str(binary), "run", "--standalone", "--format", "json", "--title", "Catalog probe", "--model", "opencode/glm-5.3-flash-free", "Reply exactly OK. Do not use tools."], cwd=work, env=env, stdin=subprocess.DEVNULL, capture_output=True, text=True, timeout=30)
print("exit:", result.returncode)
for line in result.stdout.splitlines():
event = json.loads(line)
if event.get("type") == "error":
print(json.dumps(event["error"]))
finally:
server.shutdown()
server.server_close()
import shutil
shutil.rmtree(work)Expected behavior
A valid explicitly selected model should resolve once the in-flight initial catalog fetch supplies it, rather than be reported as unavailable solely because it is absent from the bundled floor. This need not delay runs for models already present. The documented one-command standalone CI workflow has no warm-up prerequisite.
Actual behavior
The delayed-catalog probe failed in three of three fresh homes. The self-contained script above also reproduced it in a fourth fresh home:
exit: 1
{"type": "provider.no-route", "message": "Model unavailable: opencode/glm-5.3-flash-free"}
A fresh run against the normal endpoint returned OK and exit 0. With the delayed endpoint, a private server’s model list changed from missing the ID to listing it after the response completed. The subsequent standalone request produced no output within 35 seconds and was stopped; this verifies catalog refresh, not a successful warmed request.
Evidence
- Expected source: CLI command documentation documents standalone CI runs with an explicit model; the reproduction's fetched catalog contains the selected ID.
- Failure source: The published binary's four fresh-state failures above, with only the catalog response delayed locally.
- Evidence provenance: observed
- Local verification: reproduced
- Reproduction completeness: complete
Catalog startup can serve the bundled snapshot while the initial refresh runs in the background; explicit model resolution rejects a missing ID without waiting for that fetch or refreshing and retrying. The release bundle lacks this model; the current default-branch snapshot already includes it, but the startup/resolution paths remain unchanged. Current source was inspected, not executed.
Related: #50011 refreshes release snapshots; #50012 fixes a missed notification after refresh. This reproduction concerns failure while the fetch is still pending. #34837 requested fresh focused reports after lifecycle changes; #36117 concerns early partial catalog reads.
Restoration check
With a model absent from the bundle but present in a successful delayed catalog response, the first fresh standalone run should resolve that model and produce the requested reply. A model absent from both catalogs should still fail meaningfully; a bundled model should remain usable without requiring a successful network refresh.
Operating System
macOS, Darwin 27.0.0, arm64.
Terminal
Noninteractive subprocess with stdin closed.
Triage assessment
- Impact level: P2
- Assessment status: supported
- Impact basis: A valid first command fails in fresh state when the catalog fetch loses the startup race. This affects newly added models absent from the bundle; the measured delay fixture failed consistently, while the live-endpoint control succeeded. Population frequency is unknown.
- Workaround status: unverified
- Workaround basis: Polling a private server until the model appears restored catalog visibility, but the local warmed request timed out. Earlier supplied incident notes report success after warm-up; that full procedure was not verified on this release.
Activity
opencode-agent commentedon Oct 16, 2026
Thanks for the detailed report. I can reproduce this on 2.0.31, and it still happens on the latest
dev(ed772f5).What I did: in a fresh HOME/XDG state, I served the live catalog from a local endpoint via
OPENCODE_MODELS_URLwith a 3-second delay, then ranopencode run --standalone --format json --model <model> ....opencode/glm-5.3-flash-freefails with{"type":"provider.no-route","message":"Model unavailable: opencode/glm-5.3-flash-free"}. Without the delay, the same run succeeds.devalready includesglm-5.3-flash-freein its bundled catalog. So fordevthe script adds a synthetic model,opencode/repro-only-model, to the served catalog only. With the delay it fails the same way (provider.no-route). Without the delay, OpenCode finds the model and sends the request upstream.On a fresh start, OpenCode uses the bundled catalog while the first refresh runs in the background, and an explicit model that is missing is rejected straight away, without waiting for that refresh. The script below reproduces it.
Reproduction script (repro.py)
Run it:
python3 repro.pyreynold-hu commentedon Oct 19, 2026
Opened #57100. ModelsDev now exposes
readyafter the first refresh attempt; explicit model resolution waits for it (10s cap) and re-samples the catalog for up to 1s before rejecting. Bundled models resolve immediately, a failed refresh still opens the latch, and the test harnesses that build SessionContext use the offline ModelsDev fixture. Tests:readyafter refresh + a real-catalog late-model retry; full core 5551 pass with only the baseline Windows/timeout failures.reynold-hu commentedon Oct 19, 2026
The clean-branch PR is #57101 (the earlier #57100 was auto-closed as a duplicate against the pre-force-push head and cannot be reopened). #57101 has the 10-file catalog change and passes all four checks.
freshen(opencode-ci-harness): diagnose row for the fresh-home catalog…