Skip to content

Bug: opencode crashes when using OpenRouter models with a colon (:) in their identifier. #749

Closed

Description

@From-Intern-to-Engineer

The opencode CLI tool (v0.2.4) consistently fails with an "Unexpected error" when attempting to use
any custom provider model from OpenRouter whose official ID contains a colon (:), such as the :free
suffix used for some models.

The issue is not with the OpenRouter API or the user's configuration, as direct API calls using curl
to the exact same models succeed without any problems. This strongly indicates a parsing bug within
the opencode client itself.

Steps to Reproduce:

  1. Configure opencode to use OpenRouter as a custom provider by creating a
    ~/.config/opencode/.opencode.json file.

  2. Add a model to the configuration whose OpenRouter ID contains a colon. For example:

1     {
2       "providers": {
3         "openrouter": {
4           "apiKey": "${OPENROUTER_API_KEY}",
5           "baseURL": "https://openrouter.ai/api/v1",
6           "models": {
7             "gemini-2-flash": {
8                 "id": "google/gemini-2.0-flash-exp:free",
9                 "name": "Gemini 2.0 Flash"

10 }
11 }
12 }
13 }
14 }

  1. Set the OPENROUTER_API_KEY environment variable with a valid key.

  2. Run a command using the configured model:

1 opencode run -m openrouter/gemini-2-flash "This is a test prompt."

Expected Behavior:

opencode should successfully connect to the OpenRouter API and return a response from the specified
model.

Actual Behavior:

The tool immediately crashes with a generic error message.

1 > Write a short, futuristic poem about the speed of light.
2
3 @ openrouter/gemini-2-flash
4
5 Error: Unexpected error, check log file at /home/user/.local/share/opencode/log
/YYYY-MM-DDTHHMMSS.log for more details

The log file does not contain a specific error, only showing that the tool failed during the
getModel step.

Evidence & Verification:

The issue is confirmed to be with the opencode client because a direct curl request to the same
model endpoint works perfectly.

  • Failing Model: google/gemini-2.0-flash-exp:free
  • Successful curl Command:

1 curl https://openrouter.ai/api/v1/chat/completions
2 -H "Content-Type: application/json"
3 -H "Authorization: Bearer $OPENROUTER_API_KEY"
4 -d '{
5 "model": "google/gemini-2.0-flash-exp:free",
6 "messages": [
7 { "role": "user", "content": "Write a short, futuristic poem about the speed of
light." }
8 ]
9 }'

  • Result: The curl command correctly returns a JSON object with the model's response. This test was
    also successful with another model containing a colon: deepseek/deepseek-chat-v3-0324:free.

System Information:

  • opencode Version: 0.2.4
  • Operating System: darwin (macOS)

Hypothesis on Root Cause:

The presence of the colon (:) in the model ID string likely causes a parsing error within the
opencode application's logic for handling model identifiers. The application does not seem to
correctly escape or process this special character, leading to an unhandled exception and a generic
crash.

Activity

  1. drewbitt commented on Jul 8, 2025

    @drewbitt

    For reference in OpenRouter there is

    :online
    :nitro
    :floor
    :free
    :thinking
    :extended

  2. cravenceiling commented on Jul 8, 2025

    @cravenceiling
    Contributor

    What is you full config file? I suggest using a json lsp and the $schema property for json validation and autocompletion. Also, try this config, it works almost fine for me.

    {
      "$schema": "https://opencode.ai/config.json",
      "provider": {
        "openrouter": {
          "npm": "@openrouter/ai-sdk-provider",
          "name": "OpenRouter",
          "options": {
            "apiKey": "YOUR-API-KEY"
          },
          "models": {
            "deepseek/deepseek-r1-0528:free": {
              "name": "Deepseek R1 0528 (free)"
            },
            "deepseek/deepseek-chat-v3-0324:free": {
              "name": "Deepseek Chat V3 0324 (free)"
            },
            "meta-llama/llama-4-maverick:free": {
              "name": "meta-llama/llama-4-maverick:free"
            }
          }
        }
      }
    }
    
  3. lascott commented on Jul 8, 2025

    @lascott

    Same issue. Here is the ~/.config/opencode/config.json (shortend for brevity)
    opencode --print-log to start. It correctly loads the free models. I then say:

    hello

    and it dumps. ctrl-C to get' out.

    {
      "$schema": "https://opencode.ai/config.json",
      "theme": "tokyonight",
      "provider": {
        "openrouter": {
          "npm": "@openrouter/ai-sdk-provider",
          "name": "OpenRouter",
          "options": {},
          "models": {
            "openrouter/cypher-alpha:free": {
              "name": "cypher-alpha:free1M"
            },
            "deepseek/deepseek-chat-v3-0324": {
              "name": "DeepSeek Chat v3"
            },
            "deepseek/deepseek-chat-v3-0324:free": {
              "name": "DeepSeek Chat v3 free"
            },                               
          }
        }
      }
    }
    

    Error log:
    INFO 2025-07-08T11:06:27 +100ms service=default version=0.2.5 args=--print-logs opencode
    INFO 2025-07-08T11:06:27 +1ms service=app cwd=/home/louis/code/py/eod/src creating
    INFO 2025-07-08T11:06:27 +2ms service=app git=/home/louis/code/py/eod git
    INFO 2025-07-08T11:06:27 +6ms service=bus type=storage.write subscribing
    INFO 2025-07-08T11:06:27 +1ms service=app name=bus registering service
    INFO 2025-07-08T11:06:27 +0ms service=format init
    INFO 2025-07-08T11:06:27 +0ms service=bus type=file.edited subscribing
    INFO 2025-07-08T11:06:27 +0ms service=config.hooks init
    INFO 2025-07-08T11:06:27 +0ms service=bus type=file.edited subscribing
    INFO 2025-07-08T11:06:27 +0ms service=bus type=session.idle subscribing
    INFO 2025-07-08T11:06:27 +0ms service=app name=lsp registering service
    INFO 2025-07-08T11:06:27 +1ms service=lsp initializing
    INFO 2025-07-08T11:06:27 +1ms service=app name=file.watcher registering service
    INFO 2025-07-08T11:06:27 +1ms service=app name=provider registering service
    INFO 2025-07-08T11:06:27 +2ms service=app name=config registering service
    INFO 2025-07-08T11:06:27 +8ms service=config $schema=https://opencode.ai/config.json theme=tokyonight provider=[object Object] loaded
    INFO 2025-07-08T11:06:27 +3ms service=models.dev refreshing
    INFO 2025-07-08T11:06:27 +0ms service=provider init
    INFO 2025-07-08T11:06:27 +5ms service=provider providerID=openrouter found
    INFO 2025-07-08T11:06:27 +7ms service=default cmd=/home/louis/.cache/opencode/tui/tui-qgq2ycdq. tui
    INFO 2025-07-08T11:06:27 +64ms service=server method=GET path=/config request
    INFO 2025-07-08T11:06:27 +1ms service=server duration=1 response
    INFO 2025-07-08T11:06:27 +11ms service=server method=GET path=/file/status request
    INFO 2025-07-08T11:06:27 +2ms service=server method=GET path=/event request
    INFO 2025-07-08T11:06:27 +0ms service=server event connected
    INFO 2025-07-08T11:06:27 +5ms service=bus type=* subscribing
    INFO 2025-07-08T11:06:27 +3ms service=server duration=8 response
    INFO 2025-07-08T11:06:27 +6ms service=server method=GET path=/config/providers request
    INFO 2025-07-08T11:06:27 +1ms service=server duration=1 response
    INFO 2025-07-08T11:07:53 +35667ms service=bus type=* unsubscribing
    INFO 2025-07-08T11:07:53 +0ms service=server event disconnected
    INFO 2025-07-08T11:07:53 +3ms service=app name=lsp shutdown
    INFO 2025-07-08T11:07:53 +0ms service=app name=file.watcher shutdown
    INFO 2025-07-08T11:07:53 +0ms service=app name=session shutdown
    INFO 2025-07-08T11:07:53 +1ms service=app name=mcp shutdown

    Image
  4. self-assigned this
    on Jul 9, 2025
  5. rekram1-node commented on Dec 28, 2025

    @rekram1-node
    Contributor

    [automated] Closing due to 90+ days of inactivity. Feel free to reopen if you still need this!

  6. undiabler commented on Feb 6, 2026

    @undiabler

    It would be great feature since routing multiple models through openrouter is more easy than maintaining lots of different subscriptions.

    Lets reopen this!

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