Skip to content

[V2] "Unsupported package for ollama/<model>" when Ollama /api/tags takes longer than 1 s (hardcoded discovery timeout) #53341

Closed

Description

@frank-rri

Description

With a remote Ollama server (GPU host reached through an SSH tunnel, providers.ollama.settings.baseURL set to the
tunnel's local port), the first prompt of a session sometimes fails with:

Session failed: Unsupported package for ollama/qwen3.8:27b-ctx262144:

(log: SessionRunnerModel.UnsupportedPackageError: Unsupported package for ollama/...: -- the package name after the colon is empty.)

Cause, as far as I can tell from the source (packages/core/src/plugin/provider/ollama.ts, v2.0.18): model discovery calls
GET /api/tags with Effect.timeout("1 second") (line 128, also each POST /api/show, line 147). If that times out,
no models are loaded, so the provider transform never sets provider.package (line 77), and the configured model has no
package. Discovery retries every 30 s (line 181); once one attempt finishes under 1 s, everything works and the result is kept.

On our remote setup /api/tags (17 local models) typically takes about 1 s through the tunnel. Measured from a logging
proxy in front of the tunnel: on one host median 971 ms (2 of 5 calls > 1 s), on another median 1113 ms (23 of 25 calls > 1 s).
Ollama itself answers all of them with HTTP 200. We hit the error 3 times in about a week (Windows and macOS).

The 1 s limit is unchanged in v2.0.19 and v2.0.22 (and on the v2 branch at the time of writing).

Suggestion: make the discovery timeout configurable (e.g. a provider setting) or use a higher default for non-loopback
base URLs; alternatively let a configured providers.ollama entry keep a package while discovery has not succeeded yet.

Plugins

None relevant (only a local TUI status-line plugin).

OpenCode version

2.0.18 (--standalone); also checked the source of 2.0.19 and 2.0.22.

Steps to reproduce

  1. Run Ollama 0.34.2 on a remote host with a dozen or more models; reach it through an SSH tunnel so that GET /api/tags takes slightly over 1 s.
  2. Config: "providers": { "ollama": { "settings": { "baseURL": "http://127.0.0.1:<port>/v1" }, "models": { ... } } }, default model one of them.
  3. Start OpenCode and send a prompt within the first ~30 s.
  4. -> "Unsupported package for ollama/:". Sending the prompt again after a later discovery attempt succeeds works.

Operating System

Windows 11, macOS

Terminal

Windows Terminal; on macOS Terminal.app or the VS Code integrated terminal (not terminal-specific)

Activity

  1. jwefers commented on Oct 8, 2026

    @jwefers

    same now for me in v2.0.22 for llama.cpp. Still workis in v2.0.18. I have not tested the versions in between

  2. ynohat commented on Oct 24, 2026

    @ynohat

    Adding a case from vLLM, which uses the same helper (local.ts):

    • The same hard-coded 1s timeout affects vllm.ts and lmstudio.ts, not only Ollama. vLLM discovery calls /health first, so a slow /health blocks the model request too.
    • Our endpoint is reached through a security-related router that gives very poor network conditions: TCP connect about 9s, measured with curl, versus about 20 ms without it. A higher default or a configurable timeout is needed, not only a marginal fix.
    • The failure is silent. With a bare provider config (no models), discovery returns zero models, and the default INFO log has no WARN or ERROR entry. Logging discovery failures at WARN would make this diagnosable, as you suggested.

    Reproduction and measurements are in #58558.

  3. opencodejr commented on Oct 27, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report and the timings. I could reproduce this on 2.0.18, and it still happens on the latest dev (6e978118c).

    Steps:

    1. Run a mock Ollama server whose GET /api/tags takes 1.5 s.
    2. Configure providers.ollama with settings.baseURL set to http://127.0.0.1:<port>/v1 and qwen3:test listed under models.
    3. Run opencode run --standalone -m ollama/qwen3:test "hi".

    The result is Error: Unsupported package for ollama/qwen3:test: with an empty package name. The server only ever sees the /api/tags call. With a 100 ms delay, the same setup works on dev. The script below reproduces both cases.

    On current dev the discovery logic is shared by Ollama, LM Studio and vLLM in packages/core/src/plugin/provider/local.ts, and it still has the hard-coded Effect.timeout("1 second").

    Related:

    Reproduction script (repro.sh)
    #!/usr/bin/env bash
    # Reproduces #53341: Ollama discovery has a hard-coded 1 s timeout (packages/core/src/plugin/provider/local.ts);
    # when GET /api/tags takes longer, a configured ollama model fails with "Unsupported package for ollama/<model>:".
    # Usage: ./repro.sh                      (uses `opencode` on PATH)
    #        OC_DEV=/path/to/repo ./repro.sh (runs the CLI from source)
    set -u
    here=$(mktemp -d /tmp/opencode/mock-XXXX)
    # Mock Ollama server: /api/tags delayed by $DELAY ms, OpenAI-compatible chat streams a fixed reply.
    cat > "$here/mock.ts" <<'MOCK'
    // Mock Ollama: /api/tags delayed by DELAY ms (default 1500), chat completions streams "hello".
    const DELAY = Number(process.env.DELAY ?? 1500)
    const MODEL = "qwen3:test"
    const DETAILS = { format: "gguf", family: "qwen3", parameter_size: "8B", quantization_level: "Q4_K_M" }
    Bun.serve({ port: Number(process.env.PORT ?? 11999), async fetch(req) {
      const u = new URL(req.url); console.log(new Date().toISOString(), req.method, u.pathname)
      if (u.pathname === "/api/tags") { await Bun.sleep(DELAY); return Response.json({ models: [{ name: MODEL, model: MODEL, modified_at: "2026-01-01T00:00:00Z", digest: "abc", size: 1, details: DETAILS }] }) }
      if (u.pathname === "/api/show") return Response.json({ capabilities: ["completion","tools"], model_info: { "general.architecture": "qwen3", "qwen3.context_length": 32768 }, details: DETAILS })
      if (u.pathname === "/api/version") return Response.json({ version: "0.34.2" })
      if (u.pathname.endsWith("/models")) return Response.json({ object: "list", data: [{ id: MODEL, object: "model" }] })
      if (u.pathname.endsWith("/chat/completions")) {
        const chunk = (d: any) => `data: ${JSON.stringify(d)}\n\n`
        const base = { id: "x", object: "chat.completion.chunk", created: 0, model: MODEL }
        const body = chunk({ ...base, choices: [{ index: 0, delta: { role: "assistant", content: "hello from mock" }, finish_reason: null }] })
          + chunk({ ...base, choices: [{ index: 0, delta: {}, finish_reason: "stop" }], usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 } }) + "data: [DONE]\n\n"
        return new Response(body, { headers: { "content-type": "text/event-stream" } })
      }
      return new Response("nf", { status: 404 })
    }})
    MOCK
    if [ -n "${OC_DEV:-}" ]; then OC=(bun --conditions=browser src/index.ts); CWD=$OC_DEV/packages/cli
    else OC=(opencode); CWD=$(mktemp -d /tmp/opencode/proj-XXXX); fi
    run_case() { # $1=delay ms  $2=port
      (cd "$here" && DELAY=$1 PORT=$2 exec bun mock.ts > "$here/mock-$1.log" 2>&1) & local pid=$!; sleep 1
      local d; d=$(mktemp -d /tmp/opencode/case-XXXX); mkdir -p "$d/.config/opencode"
      echo "{ \"providers\": { \"ollama\": { \"settings\": { \"baseURL\": \"http://127.0.0.1:$2/v1\" }, \"models\": { \"qwen3:test\": {} } } } }" > "$d/.config/opencode/opencode.json"
      echo "=== /api/tags delay ${1} ms ==="
      (cd "$CWD" && XDG_CONFIG_HOME=$d/.config XDG_DATA_HOME=$d/.data XDG_STATE_HOME=$d/.state \
         timeout 90 "${OC[@]}" run --standalone -m ollama/qwen3:test "hi" 2>&1 | sed 's/\x1b\[[0-9;]*m//g' | tail -3)
      echo "--- mock log:"; cat "$here/mock-$1.log"; kill $pid 2>/dev/null
    }
    run_case 100 12100
    run_case 1500 12101

    Run it: bash repro.sh

  4. svenseeberg commented on Nov 11, 2026

    @svenseeberg

    Did anyone already come up with a workaround?

    /edit: my problem was actually something else. I still had an outdated line in my opencode config JSON file. I had to replace the "npm": key/value with "package": "@opencode/ai/providers/openai-compatible",

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions