BigPizzaV3/CodexPlusPlus · error · Error

请输入完整的 HTTPS API 地址

Error message

请输入完整的 HTTPS API 地址

What it means

apiEndpoint() parses the user-supplied base URL for external Chat Completions mode with new URL(). If the string cannot be parsed into a valid absolute URL (missing scheme, empty, malformed), it throws this error demanding a complete HTTPS API address.

Solutions

  1. Enter a full absolute URL including scheme, e.g. https://api.openai.com/v1 (the /chat/completions suffix is appended automatically).
  2. Trim stray whitespace/newlines from the field.
  3. Use the provider's documented base URL, not a page URL or relative path.

Example fix

// before
baseUrl = 'api.example.com/v1';
// after
baseUrl = 'https://api.example.com/v1';
Defensive patterns

Strategy: validation

Validate before calling

function validBaseUrl(raw){ try { const u = new URL(String(raw).trim()); return u.protocol === 'http:' || u.protocol === 'https:'; } catch { return false; } }

Type guard

const isAbsoluteUrl = (s) => { try { new URL(s); return true; } catch { return false; } };

Try / catch

try { saveExternalApiSettings(input); } catch (e) { if (e.message.includes('HTTPS API 地址')) showFieldError('baseUrl', '必须为完整 https:// 地址'); }

Prevention

When it happens

Trigger: Saving external-API settings where baseUrl is empty, lacks a scheme (e.g. 'api.example.com/v1' without https://), or is otherwise not an absolute URL.

Common situations: User pasted a host without https://; left the field blank; pasted a relative path; copy/paste introduced whitespace or a broken URL.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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

Appendix: source

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

  // resume reads the existing response instead of launching duplicate work.
  for(;;){
    signal?.throwIfAborted();
    const conversation=manager.getConversation(session.sideId);
    if(!conversation)throw Error('后台整理会话已失效,已完成批次仍保留;点击继续可重新处理本批');
    const turn=nativeTurns(conversation).find(t=>t.turnId===session.turnId);
    if(turn&&turn.status!=='inProgress'){
      if(turn.status!=='completed'||turn.error){session.requestId=null;session.turnId=null;session.phase='ready';await save();throw Error('本批整理中断,已完成批次已保存,可点击继续');}
      if(session.phase!=='completed')session.batches=(session.batches||0)+1;
      session.phase='completed';await save();
      return turn.items.filter(i=>i.type==='agentMessage'&&(i.phase==null||i.phase==='final_answer')).map(i=>i.text??'').join('\n');
    }
    await new Promise(resolve=>setTimeout(resolve,1000));
  }
}

  // 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){

View on GitHub (pinned to b1ed92e5e4)