opencode: stale Zen model.base_url survives a switch to an opencode-go model → 401 "Model is not supported" (normalize_opencode_base_url never rewrites the family path)
Summary
Switching to an opencode-go-only model while config.yaml's model.base_url is pinned to the Zen relay leaves the base URL pointing at Zen. The provider flips to opencode-go, the URL does not, and every request fails:
provider=opencode-go base_url=https://opencode.ai/zen/v1 model=mimo-v2.5
-> HTTP 401: Model mimo-v2.5 is not supported
mimo-v2.5 / mimo-v2.5-pro are Go-subscription models (GET /zen/go/v1/models lists them; GET /zen/v1/models does not), so the Zen relay is correct to reject them — the bug is that we asked Zen at all.
The desktop app is unaffected because it resolves the base URL from the model catalog per session; the CLI inherits the pinned model.base_url override. Both run the same backend, so the only difference is which URL the client is built with.
Environment
- Hermes Agent v0.21.3 (2026.9.14), upstream
3c3ab69a, install method: git - Windows 11, install dir
%LOCALAPPDATA%\hermes - Provider: built-in
opencode-go; credential present in the pool and valid
Steps to reproduce
- Have
config.yamlin the state left behind by previously using an OpenCode Zen model:model: default: mimo-v2.5-free provider: opencode base_url: https://opencode.ai/zen/v1 - Switch to a Go-only model:
hermes -m mimo-v2.5 --provider opencode-go - Send any message.
Actual: HTTP 401: Model mimo-v2.5 is not supported, with provider=opencode-go base_url=https://opencode.ai/zen/v1.
Expected: the client is built against https://opencode.ai/zen/go/v1 and the request succeeds.
Evidence
errors.log, provider already correctly resolved to opencode-go but URL still on Zen:
2026-09-16 12:14:22,781 ERROR agent.chat_completion_helpers: Streaming failed before delivery:
Error code: 401 - {'type': 'error', 'error': {'type': 'ModelError', 'message': 'Model mimo-v2.5 is not supported'}}
2026-09-16 12:14:22,788 WARNING agent.conversation_loop: API call failed (attempt 1/3)
error_type=AuthenticationError provider=opencode-go base_url=https://opencode.ai/zen/v1 model=mimo-v2.5
summary=HTTP 401: Model mimo-v2.5 is not supported
Interestingly the session's persisted model_config had the right URL in gateway_runtime while the client used the wrong one:
{"model": "mimo-v2.5",
"gateway_runtime": {"provider": "opencode-go", "base_url": "https://opencode.ai/zen/go/v1", "api_mode": "chat_completions"},
"provider": "opencode-go", "base_url": "https://opencode.ai/zen/v1"}
Per-session billing rows (state.db, session_model_usage) across this install — mimo-v2.5 has never succeeded from the CLI, only from desktop:
| source | model | billing_provider | billing_base_url | calls |
|---|---|---|---|---|
| desktop | mimo-v2.5 | opencode-go | https://opencode.ai/zen/go/v1 |
31 |
| cli | mimo-v2.5-free | opencode-zen | https://opencode.ai/zen/v1 |
1 |
| tui | mimo-v2.5-free | opencode-zen | https://opencode.ai/zen/v1 |
1 |
Root cause
normalize_opencode_base_url() (hermes_cli/models.py, present on current origin/main) is the only healing step applied to a carried-over OpenCode base URL, and it only ever touches the /v1 suffix — never the family path segment (/zen vs /zen/go):
url = str(base_url or "").strip().rstrip("/")
if not url or opencode_provider_family(provider_id) is None:
return url
if api_mode == "anthropic_messages":
return re.sub(r"/v1$", "", url)
if url.endswith("/v1"):
return url # <-- https://opencode.ai/zen/v1 returns unchanged for an opencode-go provider
...
So ("opencode-go", "chat_completions", "https://opencode.ai/zen/v1") returns the Zen URL untouched. Nothing else downstream reconciles the URL against the resolved provider family.
Suggested fix
When opencode_provider_family(provider_id) resolves and the host is opencode.ai, rewrite the family path segment to match the family (opencode-go -> /zen/go/v1, opencode/opencode-zen/opencode-free -> /zen/v1) instead of only healing the /v1 suffix. Custom OPENCODE_*_BASE_URL proxies on non-opencode.ai hosts should keep the existing passthrough behaviour.
Workaround: pin model.base_url: https://opencode.ai/zen/go/v1 in config.yaml by hand. Verified — after that change the same CLI invocation succeeds and bills against https://opencode.ai/zen/go/v1.
Related
- #100854 — also opencode-go + wrong outbound URL, but the
anthropic_messagesroute and a 404; different surface. - #105947 — opencode-free missing
/v1; same function, the suffix case it does handle. - #65587 — model override not re-resolving provider transport; adjacent lifecycle issue.
Source: NousResearch/hermes-agent