BigPizzaV3/CodexPlusPlus · error
Base URL 不能为空
Error message
Base URL 不能为空
What it means
test_relay_profile 是「测试供应商连通性」的 async 入口:向 {base_url}/responses 或 /chat/completions 发一次最小请求。发送前先取 relay_profile_base_url(profile) 并 trim、去掉尾部斜杠,若结果为空则 bail,不会发起任何网络请求。
Source
Thrown at crates/codex-plus-core/src/relay_config.rs:529
}))?;
let backup_path =
write_codex_live_atomic(home, Some(&updated), Some(auth_contents.as_bytes()), false)?;
let status = relay_config_status_from_home(home);
Ok(RelayApplyResult {
config_path: status.config_path,
backup_path,
configured: status.configured,
})
}
pub async fn test_relay_profile(
profile: &RelayProfile,
model: &str,
) -> anyhow::Result<RelayProfileTestResult> {
let base_url = relay_profile_base_url(profile);
let base_url = base_url.trim().trim_end_matches('/');
if base_url.is_empty() {
anyhow::bail!("Base URL 不能为空");
}
let api_key = relay_profile_api_key(profile);
let api_key = api_key.trim();
if api_key.is_empty() {
anyhow::bail!("API Key 不能为空");
}
let client = crate::http_client::proxied_client("CodexPlusPlus/RelayTest")?;
let endpoint = match profile.protocol {
RelayProtocol::Responses => format!("{base_url}/responses"),
RelayProtocol::ChatCompletions => format!("{base_url}/chat/completions"),
};
let test_model = model.trim();
if test_model.is_empty() {
anyhow::bail!("测试模型不能为空");
}
let payload = relay_profile_test_payload(profile.protocol, test_model);View on GitHub (pinned to 1f431ae49b)
Solutions
- 先保存 profile 的 base_url 再点测试
- 调用前检查 relay_profile_base_url(profile).trim().trim_end_matches('/') 非空
- 对 Aggregate 类型 profile 不要直接调用本函数测试
Example fix
// before
let r = test_relay_profile(&empty_profile, "gpt-5").await?;
// after
let base = relay_profile_base_url(&profile).trim().trim_end_matches('/').to_string();
if base.is_empty() {
return Err(anyhow::anyhow!("Base URL 不能为空"));
}
let r = test_relay_profile(&profile, "gpt-5").await?; Defensive patterns
Strategy: validation
Validate before calling
let base = relay_profile_base_url(profile).trim().trim_end_matches('/').to_string();
if base.is_empty() {
return Err(anyhow::anyhow!("Base URL 不能为空"));
}
test_relay_profile(profile, model).await?; Try / catch
if let Err(err) = test_relay_profile(&profile, &model).await {
if err.to_string().contains("Base URL 不能为空") {
// 提示先保存 base_url;不发网络重试
} else { return Err(err); }
} Prevention
- 测试按钮仅在 profile 的 base_url 非空时可用
- 注意 "//" 或 "/" 这类值 trim 斜杠后也会判空
- Aggregate 类型 profile 不要直接调用单 profile 测试
When it happens
Trigger: 调用 test_relay_profile(profile, model) 时 profile 的 base_url 解析结果为空,或仅由斜杠/空白组成(如 "//" 或 "/"——trim_end_matches('/') 会把斜杠剥光变成空串)。
Common situations: 在 UI 上没保存 base_url 就点「测试」;base_url 只填了域名后缀斜杠;Aggregate 模式 profile 没有独立 base_url。
Related errors
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/798a61e5763105be.
Report an issue: GitHub.