OpenCode 配置 Base URL 后报 model_not_found?用 opencode.json 和 /v1/models 修正模型 ID

OpenCode 配置 Base URL 后报 model_not_found?用 opencode.json 和 /v1/models 修正模型 ID

如果 OpenCode 已经能启动,自定义 Provider 也出现在列表里,但第一次请求返回model_not_found,先不要继续换 Key。这个错误通常说明请求已经到达兼容接口,只是配置里的模型 ID 不在服务端模型目录中;如果同时把 Base URL 写成了带/v1的地址,又在客户端字段里重复拼接/v1,还会叠加一个路径 404。

本文用 OpenCode CLI 1.18.4 和一个不连接外网的 OpenAI-compatible 本地夹具复现完整链路:先读取/v1/models,再把返回的精确 ID 写入opencode.json,最后用一次流式请求验证。夹具只使用合成模型名和合成 Key,不代表任何线上服务的兼容性结论。

先给可复制结论

适用环境

• OpenCode CLI 1.18.4;其他版本先用opencode --version确认配置语法是否一致。

• macOS、Linux 或 WSL 终端;本文命令使用 POSIX shell。

• 一个提供 OpenAI-compatible/v1/models/v1/chat/completions的接口。

• 项目根目录下的opencode.json。本文没有把真实密钥写入文件,示例中的synthetic-fixture-only只用于本地夹具。

最小配置

先把baseURL写到版本路径/v1,不要再在模型或请求路径中重复拼接/v1models中的键必须与服务端返回的data[].id完全相同,大小写、连字符和版本后缀都不能凭感觉改写。

{ "$schema": "https://opencode.ai/config.json", "provider": { "fixture": { "npm": "@ai-sdk/openai-compatible", "name": "Local OpenAI-compatible fixture", "options": { "baseURL": "http://127.0.0.1:18275/v1", "apiKey": "synthetic-fixture-only" }, "models": { "fixture-correct": {} } } } }

真实环境中把baseURL换成服务端公布的兼容 API 根地址,把认证信息交给安全的凭据管理方式;不要把真实 Key 粘贴到文章、仓库或终端历史。配置保存后,先执行模型目录检查:

opencode --version curl -sS http://127.0.0.1:18275/v1/models opencode models fixture

本次的成功信号是:opencode --version输出1.18.4curl返回模型 IDfixture-correct,而opencode models fixture输出fixture/fixture-correct。最后执行一次最小请求:

opencode run --pure --model fixture/fixture-correct \ 'Reply with exactly OPENCODE_LOCAL_FIXTURE_OK.'

终端输出OPENCODE_LOCAL_FIXTURE_OK,并且夹具日志显示请求路径为POST /v1/chat/completions、模型为fixture-correct,才算这条配置链路跑通。

一、先确认模型 ID,不要手写显示名称

OpenCode 配置里的models是客户端可选择的模型集合。它不是“模型推荐列表”,更不是可以把产品页面上的展示名随便复制过来的备注。兼容服务最终按请求体中的model字段路由,因此最可靠的顺序是:

1. 读取当前端点的/v1/models

2. 找到响应中的data[].id

3. 原样复制 ID 到opencode.jsonmodels对象。

4. 用opencode models <provider>检查 OpenCode 能否看到相同的provider/model

5. 再执行最小对话请求。

本地夹具返回的目录如下:

{ "object": "list", "data": [ { "id": "fixture-correct", "object": "model", "owned_by": "local-fixture" } ] }

因此正确配置是fixture-correct,而不是local-fixturefixture或一个从其他服务复制来的模型名。服务端返回的owned_by只是元数据,不能代替id

如果接口需要额外的请求头或特定的认证格式,也要先看它的 OpenAI-compatible 说明。/v1/models能返回 200,只能证明模型目录这个请求可达;它不能证明该模型支持 OpenCode 的所有能力,更不能证明工具调用、长上下文或生产稳定性。

二、区分两类 404

1. 路径 404:Base URL 被重复拼接

如果配置已经是:

https://example.invalid/v1

客户端通常会在此基础上请求/models/chat/completions。不要再把配置改成:

https://example.invalid/v1/v1

本次夹具的对照结果是:

GET /v1/models -> 200 GET /v1/v1/models -> 404 not_found

这时错误重点是路径拼接,不是模型不存在。可以先用 curl 验证根路径:

BASE_URL=http://127.0.0.1:18275/v1 curl -sS "$BASE_URL/models" curl -sS "${BASE_URL%/v1}/v1/v1/models"

把返回 200 的那条路径固定下来,再回到 OpenCode 配置。不要为了“试试看”同时改 Base URL、模型 ID 和认证信息,否则一次请求失败后无法判断到底是哪一层变化产生了影响。

2. 模型 404:路径正确但 ID 不在目录

用独立的错误配置把模型写成fixture-wrong,再运行同一个最小请求:

OPENCODE_CONFIG=opencode-wrong.json \ opencode run --pure --model fixture/fixture-wrong \ 'Reply with exactly WRONG_MODEL_SHOULD_FAIL.'

本次实际输出为:

> build · fixture-wrong Error: model_not_found: fixture-wrong

夹具日志同时记录到两次POST /v1/chat/completions,模型字段都是fixture-wrong,说明 OpenCode 确实把这个 ID 发给了接口。这里不应该继续重试同一个模型,也不应该把错误模型名改成一个“看起来更像”的名称;重新读取/v1/models才是修复动作。

修正为fixture-correct后,实际结果为:

> build · fixture-correct OPENCODE_LOCAL_FIXTURE_OK

状态码和成功文本是两层信号:HTTP 200 只能说明请求返回成功,正文中的固定标记才证明当前测试提示词已经得到响应。线上服务应把固定标记替换成无敏感信息的短句,并保留请求时间、路径、模型和错误码,方便回查。

三、按字段顺序排查 OpenCode

第 1 步:确认实际读取的配置

在项目根目录执行:

pwd ls -la opencode.json opencode --version

常见误区是把配置放在编辑器打开的目录,却从另一个目录启动 OpenCode;或者复制了一个旧的opencode.json,以为当前会话已经使用了新内容。先确认文件路径和当前工作目录,再检查 JSON 是否能被读取。

第 2 步:只改一个字段做验证

建议按以下顺序锁定变量:

1. 固定 Provider ID,例如fixture

2. 固定npm适配器为@ai-sdk/openai-compatible

3. 固定baseURL,只保留一个/v1

4. 从/v1/models复制真实id

5. 最后再替换认证信息。

如果第一步就返回 401,说明认证层还没有通过;如果返回404 not_found,优先看路径;如果返回404 model_not_found,优先看model字段;如果得到 200 但 OpenCode 仍无输出,再检查流式事件格式和客户端日志。不要把这些情况都归结为“Key 失效”。

第 3 步:让 OpenCode 输出它可选择的模型

配置中保留真实模型 ID 后运行:

opencode models fixture

本次显示为:

fixture/fixture-correct

命令能列出模型,说明配置解析和 Provider 识别已经通过;但它仍不是请求成功的替代品,所以必须继续执行一次opencode run。如果这里没有任何模型,检查provider名称、models对象是否位于正确层级,以及当前目录是否真的有这份配置。

四、最小失败矩阵

现象 优先检查 不能直接下的结论

--- --- ---

Provider not found当前目录、Provider ID、配置文件是否被读取 不能说端点不可用

/v1/v1/models返回 404baseURL是否已经含/v1不能说模型不存在

model_not_found/v1/modelsdata[].id与配置是否完全一致 不能说 Key 失效

401/Unauthorized 认证字段、Key 归属与权限 不能通过换模型修复

/v1/models为 200、对话仍失败 请求体、流式事件和模型能力 不能说已兼容所有工作流

OpenCode 输出成功但平台无记录 请求是否到达预期端点、使用的 Key 归属 不能把本地成功归因到另一个账号

五、实测边界与安全说明

本次验证只覆盖 OpenCode 1.18.4、@ai-sdk/openai-compatible、本地/v1/models、流式/v1/chat/completions、一个错误模型和一个正确模型。夹具的响应是我自己生成的,模型名、Key 和成功标记都不是线上凭据或真实用户数据。

如果你要把同一套方法迁移到线上接口,至少重新确认四件事:服务端实际 Base URL、认证方式、当日/v1/models返回的精确 ID,以及最小对话请求的成功响应。不要把本文的fixture-correct当作其他服务的模型名,也不要根据一次 200 响应承诺稳定性、速度或所有工具能力。

总结

OpenCode 遇到model_not_found时,最短的正确路径不是盲目换 Key,而是固定配置读取位置,确认 Base URL 只包含一个/v1,读取/v1/models,把data[].id原样写入opencode.json,再用一次最小流式请求验证。路径 404、模型 404 和认证 401 要分层处理;只有看见明确的成功信号,才算完成配置。