BigPizzaV3/CodexPlusPlus · error
请填写 API 的模型名称
Error message
请填写 API 的模型名称
What it means
For the external channel, apiConfig() requires a non-empty model name of at most 200 characters after trimming. The model name is sent to the OpenAI-compatible Chat Completions endpoint and cannot be inferred. This error means the model field was empty or exceeded 200 chars.
Solutions
- Fill in the exact model identifier the provider expects, e.g. 'gpt-4o' or 'deepseek-chat'
- Check the provider's models endpoint (/v1/models) for the exact spelling
- Ensure the saved config object actually contains a non-empty model string before calling apiConfig
- Shorten the model string if it exceeded 200 characters (it should never be that long)
Example fix
// before
apiConfig({channel:'external',baseUrl:'https://api.example.com/v1',model:''})
// after
apiConfig({channel:'external',baseUrl:'https://api.example.com/v1',model:'gpt-4o',key:'sk-...'}) Defensive patterns
Strategy: validation
Validate before calling
const model = String(input?.model || '').trim();
if (!model) throw new Error('请填写 API 的模型名称');
if (model.length > 200) throw new Error('model name too long'); Type guard
function hasModel(c) { return typeof c?.model === 'string' && c.model.trim().length > 0 && c.model.trim().length <= 200; } Try / catch
let cfg;
try { cfg = apiConfig(formValues); } catch (e) { if (String(e).includes('模型名称')) focusModelField(); return; } Prevention
- Make the model field required in the settings form UI
- Populate a model dropdown from GET /v1/models when the provider supports it
- Persist the model along with baseUrl so partial restores don't drop it
- Validate the whole external-channel config as a unit before saving
When it happens
Trigger: apiConfig({channel:'external',baseUrl:'https://api.example.com/v1',model:''}) or model length > 200; also thrown via readApiForm/config callers when the settings form was saved with a blank model.
Common situations: User picks 'external API' channel but forgets to fill the model dropdown/text; model name truncated by paste; user copies a base URL but not the model; migration restored a config without a model field.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- 官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的…
- Base URL 不能为空
- 上游 Base URL 不能为空
- 图片上游 Base URL 不能为空
- Base URL 缺少主机名
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/607ac10605de7cdf.
Report an issue: GitHub.
Appendix: source
Thrown at tools/conversation-canvas/external-api.mjs:15
// OpenAI-compatible Chat Completions. Never persist credentials in tree checkpoints.
export function apiEndpoint(raw){
let url;try{url=new URL(String(raw).trim());}catch{throw Error('请输入完整的 HTTPS API 地址');}
if(url.protocol!=='https:'||url.username||url.password||url.search||url.hash)throw Error('API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段');
const path=url.pathname.replace(/\/+$/,'');
url.pathname=path.endsWith('/chat/completions')?path:(path||'/v1')+'/chat/completions';
return url.href;
}
export function apiConfig(input){
const channel=input?.channel==='external'?'external':'native';
const value={channel,baseUrl:String(input?.baseUrl||'').trim(),model:String(input?.model||'').trim(),key:String(input?.key||'').trim(),remember:input?.remember===true,speed:input?.speed==='provider'?'provider':'fast',revision:input?.revision||crypto.randomUUID()};
if(channel==='external'){
value.endpoint=apiEndpoint(value.baseUrl);
if(!value.model||value.model.length>200)throw Error('请填写 API 的模型名称');
if(!value.key||/[\r\n]/.test(value.key))throw Error('请在设置中填写有效 API Key');
}
return value;
}
export function storedApiConfig(config){
const {channel,baseUrl,model,remember,speed,revision}=config;
return {channel,baseUrl,model,remember,speed,revision,...remember?{key:config.key}:{}};
}
export function apiError(error){
if(error?.name==='AbortError')return error;
if(error?.canvasApiLocal===true)return error;
const code=Number(error?.status??error?.responseStatus);
const hint={401:'密钥无效或已过期',403:'接口拒绝访问,请检查权限',404:'地址或模型不存在',408:'接口请求超时',413:'本批资料超过接口大小限制',429:'接口限流或额度不足'}[code];
// Provider messages can echo request contents and Authorization; never display them.
return Object.assign(Error(hint?`API ${code}:${hint}`:code>=400?`API 请求失败(HTTP ${code}),请检查服务状态`:'API 连接失败,请检查地址、网络及服务状态'),{retryable:!code||code===408||code===429||code>=500});
}View on GitHub (pinned to b1ed92e5e4)