BigPizzaV3/CodexPlusPlus · error · Error

请在设置中填写有效 API Key

Error message

请在设置中填写有效 API Key

What it means

For the external API channel, apiConfig() requires a non-empty API key containing no CR/LF characters. A missing or newline-contaminated key would break the Authorization header and leak across lines, so it throws immediately.

Solutions

  1. Enter a valid API key in the settings panel
  2. Re-copy the key making sure there are no trailing newlines or spaces
  3. Enable 'remember' to persist the key so it is not empty next session
  4. Confirm the provider key is active and not revoked

Example fix

// before
const key = document.querySelector('#key').value; // "sk-abc\n"
// after
const key = document.querySelector('#key').value.replace(/[\r\n]/g,'').trim();
Defensive patterns

Strategy: validation

Validate before calling

const key=(input.key||'').trim();
if(input.channel==='external' && (!key || /[\r\n]/.test(key))) throw new Error('请在设置中填写有效 API Key');

Type guard

function hasValidKey(cfg){return typeof cfg?.key==='string' && cfg.key.trim().length>0 && !/[\r\n]/.test(cfg.key);}

Try / catch

try{ cfg=apiConfig(input); }catch(e){ if(e.message.includes('API Key')) showKeyInputError(); }

Prevention

When it happens

Trigger: apiConfig with channel='external' and input.key empty after trim, or containing \r or \n characters.

Common situations: User forgot to fill the API Key field; pasted a key with a trailing newline from clipboard; key stored from a multi-line paste; remember=false so the key was not persisted and is empty on next run.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/ba28c3f0f9e91552. Report an issue: GitHub.

Appendix: source

Thrown at tools/conversation-canvas/public/canvas.user.js:635

  }
}

  // OpenAI-compatible Chat Completions. Never persist credentials in tree checkpoints.
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;
}

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

function storedApiConfig(config){
  const {channel,baseUrl,model,remember,speed,revision}=config;
  return {channel,baseUrl,model,remember,speed,revision,...remember?{key:config.key}:{}};
}

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)