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

Closed
opened 2026-02-16 17:27:14 -05:00 by yindo · 5 comments
Owner

Originally created by @From-Intern-to-Engineer on GitHub (Jul 7, 2025).

Originally assigned to: @thdxr on GitHub.

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.

Originally created by @From-Intern-to-Engineer on GitHub (Jul 7, 2025). Originally assigned to: @thdxr on GitHub. 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 } 3. Set the OPENROUTER_API_KEY environment variable with a valid key. 4. 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.
yindo closed this issue 2026-02-16 17:27:14 -05:00
Author
Owner

@drewbitt commented on GitHub (Jul 7, 2025):

For reference in OpenRouter there is

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

@drewbitt commented on GitHub (Jul 7, 2025): For reference in OpenRouter there is :online :nitro :floor :free :thinking :extended
Author
Owner

@cravenceiling commented on GitHub (Jul 7, 2025):

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"
        }
      }
    }
  }
}

@cravenceiling commented on GitHub (Jul 7, 2025): 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. ```json { "$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" } } } } } ```
Author
Owner

@lascott commented on GitHub (Jul 8, 2025):

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
@lascott commented on GitHub (Jul 8, 2025): 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 <img width="827" height="799" alt="Image" src="https://github.com/user-attachments/assets/5319fe8b-8bef-46c6-8d17-0b31f5776078" />
Author
Owner

@rekram1-node commented on GitHub (Dec 27, 2025):

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

@rekram1-node commented on GitHub (Dec 27, 2025): [automated] Closing due to 90+ days of inactivity. Feel free to reopen if you still need this!
Author
Owner

@undiabler commented on GitHub (Feb 6, 2026):

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

Lets reopen this!

@undiabler commented on GitHub (Feb 6, 2026): It would be great feature since routing multiple models through openrouter is more easy than maintaining lots of different subscriptions. Lets reopen this!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#541