Skip to content

createOpencodeServer({config}) / OPENCODE_CONFIG_CONTENT is invisible to the v2 API surface (ModelUnavailableError for custom providers) #36748

Closed as not planned

Description

@doryokujin

Summary

A custom provider using npm: "@ai-sdk/anthropic" (an Anthropic Messages-API-compatible endpoint) fails at model-resolve time with ModelUnavailableError, even though the provider and its model show up in GET /config/providers (including under default). This blocks routing to the custom provider entirely; with no explicit model, opencode silently falls back to its built-in OpenCode Zen model instead.

Environment

  • opencode 1.17.18 (also reproduced on 1.17.16, installed in isolation — both fail identically, so not a recent regression)
  • macOS (arm64), Bun
  • Reproduces on a bare bun init project, so it is not app-specific.

Config (matches the documented custom-provider schema)

{
  "model": "myproxy/claude-haiku-4-5-20251001",
  "provider": {
    "myproxy": {
      "npm": "@ai-sdk/anthropic",
      "name": "my proxy",
      "options": { "baseURL": "http://127.0.0.1:18080/v1", "apiKey": "proxy-mode" },
      "models": { "claude-haiku-4-5-20251001": { "name": "claude-haiku-4-5-20251001" } }
    }
  }
}

Repro

bun init -y
bun add @opencode-ai/sdk @ai-sdk/anthropic
import { createOpencodeServer } from "@opencode-ai/sdk";
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client";

const config = { /* the config above */ };
const server = await createOpencodeServer({ hostname: "127.0.0.1", config });
const c = createOpencodeClient({ baseUrl: server.url });
const M = { id: "claude-haiku-4-5-20251001", providerID: "myproxy" };
const s = await c.v2.session.create({ model: M }, { throwOnError: true });
await c.v2.session.prompt({ sessionID: s.data.data.id, prompt: { text: "hi" }, model: M }, { throwOnError: true });

Server log:

ERROR message="Failed to drain Session" cause="SessionRunnerModel.ModelUnavailableError: Model unavailable: myproxy/claude-haiku-4-5-20251001
    at SessionRunnerModel.resolve ..."

The endpoint does not need to be reachable — resolve() throws before any network call, so this repros with nothing running on :18080.

What I ruled out

  • opencode version — 1.17.16 and 1.17.18 both fail.
  • Config shape — matches the custom-provider docs (npm + name + options.baseURL + models[].name).
  • models.dev reachability — reachable (HTTP 200) when tested; still fails.
  • Model metadata — adding limit/cost/capabilities to the model entry doesn't help.
  • Package availability — on my machine @ai-sdk/anthropic was absent system-wide and opencode did not auto-install it; installing it in the process's cwd node_modules and via bun add -g both left resolve() failing.

Questions

  1. Is opencode expected to auto-install a custom provider's npm package? If so, where, and is there a way to see/trigger that install (it never produced any @ai-sdk/anthropic on disk here)?
  2. If the package must be provided by the user, where does opencode's compiled binary resolve custom-provider packages from? (cwd node_modules and bun global both seem ignored.)

Happy to provide more logs. This may be partly environment-specific on my side, but the "provider listed in /config/providers yet ModelUnavailable at resolve" behavior seems worth clarifying regardless.

Activity

  1. github-actions commented on Jul 13, 2026

    @github-actions
    Contributor

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

    In particular, #33888 documents that provider.npm is only consulted inside the loop over explicitly listed provider.models entries, which may interact with how the resolver locates the installed package on disk. Your question about where opencode resolves custom provider packages from is directly relevant to that issue.

  2. doryokujin commented on Jul 14, 2026

    @doryokujin
    Author

    Update — root cause found. It is not npm package resolution; this issue's original framing (and title) was wrong. Retitling accordingly.

    Source-diving v1.17.18 explains everything observed above:

    1. The v2 session runner never loads provider npm packages. packages/core/src/session/runner/model.ts (fromCatalogModel / supported) ships built-in protocol implementations (@opencode-ai/llm: AnthropicMessages / OpenAIResponses / OpenAICompatibleChat) and selects one by the string value of the catalog model's api.package. On the v2 path, npm: "@ai-sdk/anthropic" is only ever compared as a string — installing the package (cwd node_modules, bun add -g, anywhere) cannot matter, which is why all the placement experiments in this report failed.

    2. ModelUnavailableError just means "model not in the v2 catalog", and the v2 Config service (packages/core/src/config.ts) loads config files only — opencode.json/.jsonc discovered from the location directory up to the project root, plus the global config dir. It never reads OPENCODE_CONFIG_CONTENT, which is the only thing the SDK's createOpencodeServer({ config }) sets (packages/sdk/js/src/v2/server.ts). Config passed through the SDK is therefore invisible to the entire v2 API surface — while v1 endpoints like /config/providers, whose loader does read OPENCODE_CONFIG_CONTENT (packages/opencode/src/config/config.ts), happily report the provider. That split is exactly the confusing symptom in the original report.

    Confirmed empirically on 1.17.18 (identical v1-shape provider config in each case; mock Anthropic Messages endpoint on 127.0.0.1):

    Where the provider config lives GET /api/provider (v2 catalog) prompt
    createOpencodeServer({ config }) absent ModelUnavailableError
    opencode.json in the served dir (git repo) present — migrated to api: {type:"aisdk", package:"@ai-sdk/anthropic", url} works, emits POST /v1/messages
    opencode.json in a non-git dir absent —
    dir pointed to by OPENCODE_CONFIG_DIR absent —

    Actionable items hiding in this report, stated precisely:

    • SDK/server contract gap (the headline): createOpencodeServer({ config }) silently does nothing for the v2 API surface. Either the v2 Config service should ingest OPENCODE_CONFIG_CONTENT, or the SDK option should be documented as v1-only.
    • Config discovery requires the served directory to be inside a git project; the same file in a non-git directory is silently ignored.
    • OPENCODE_CONFIG_DIR is honored by the v1 loader only, not the v2 catalog.

    Workaround for anyone landing here: put the provider block in an opencode.json inside a git repo and run the server from there — works on both 1.17.16 and 1.17.18. (This also disproves the earlier "environment / on-demand install" hypothesis in the thread: which behavior you get depends on which API surface the client drives — v1 reads the SDK-passed config, v2 doesn't — not on the machine.)

  3. changed the title [-]Custom @ai-sdk/anthropic provider: ModelUnavailableError at resolve despite provider listed in /config/providers[/-] [+]createOpencodeServer({config}) / OPENCODE_CONFIG_CONTENT is invisible to the v2 API surface (ModelUnavailableError for custom providers)[/+] on Jul 14, 2026
  4. github-actions commented on Sep 13, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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