BigPizzaV3/CodexPlusPlus · error
中转 Base URL 不能为空
Error message
中转 Base URL 不能为空
What it means
Thrown by `apply_relay_config_to_home_with_session_provider` in relay_config.rs when the `base_url` argument is empty after trimming. This function writes the relay provider entry into the codex home config.toml; without a base URL the generated `model_provider` would have no endpoint, so the apply aborts before touching files. It is the first validation in the apply pipeline.
Solutions
- Pass the relay endpoint (e.g. "https://relay.example.com") as base_url.
- Load and validate the saved profile before applying; reject blank base_url in the UI.
- If a default endpoint exists for the protocol, substitute it before calling the apply function.
Example fix
// before apply_relay_config_to_home_with_protocol(home, "", key, protocol, port, sp).await?; // after apply_relay_config_to_home_with_protocol(home, "https://relay.example.com", key, protocol, port, sp).await?;
Defensive patterns
Strategy: validation
Validate before calling
let base_url = base_url.trim();
anyhow::ensure!(!base_url.is_empty(), "中转 Base URL 不能为空");
anyhow::ensure!(base_url.starts_with("http"), "中转 Base URL 必须是 http(s) URL"); Type guard
fn valid_base_url(url: &str) -> bool {
let u = url.trim(); u.starts_with("http://") || u.starts_with("https://")
} Try / catch
match apply_relay_config_to_home_with_protocol(home, url, key, proto, port, sp).await {
Ok(r) => info!("applied: {:?}", r),
Err(e) if e.to_string().contains("中转 Base URL 不能为空") => warn!("profile missing endpoint; skipping apply"),
Err(e) => return Err(e),
} Prevention
- Load relay profiles through a validation layer that rejects blank endpoints at save time.
- Resolve defaults per protocol before calling apply.
- Write an integration test that applies each stored profile to catch blank-field regressions.
When it happens
Trigger: Calling `apply_relay_config_to_home_with_protocol` / `apply_relay_config_to_home_with_session_provider` with `base_url = ""` or `" "`; bails at relay_config.rs:401 before bearer-token and session-provider checks.
Common situations: A relay profile was saved without an endpoint; a UI passed an empty string because the profile field was never filled; refactoring code that previously defaulted the URL now passes an empty value.
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
- Base URL 为空
- config.toml 内容不能为空
- 中转 Key 不能为空
- API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段
- API 地址须使用 HTTPS,且不含账号、密码、查询参数或片段
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/1da5718ff11cb388.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/relay_config.rs:401
base_url,
bearer_token,
protocol,
proxy_port,
RelaySessionProvider::Custom,
)
}
pub fn apply_relay_config_to_home_with_session_provider(
home: &Path,
base_url: &str,
bearer_token: &str,
protocol: RelayProtocol,
proxy_port: u16,
session_provider: RelaySessionProvider,
) -> anyhow::Result<RelayApplyResult> {
let base_url = base_url.trim();
if base_url.is_empty() {
anyhow::bail!("中转 Base URL 不能为空");
}
let bearer_token = bearer_token.trim();
if bearer_token.is_empty() {
anyhow::bail!("中转 Key 不能为空");
}
if session_provider == RelaySessionProvider::Openai && protocol != RelayProtocol::Responses {
anyhow::bail!("OpenAI 会话身份仅支持 Responses API");
}
let codex_base_url = codex_base_url_for_protocol(base_url, protocol, proxy_port);
let updated = upsert_model_provider_config_with_session_provider(
"",
&codex_base_url,
bearer_token,
true,
session_provider,
)?;
let auth_contents = serde_json::to_string_pretty(&json!({
"OPENAI_API_KEY": bearer_tokenView on GitHub (pinned to b1ed92e5e4)