BigPizzaV3/CodexPlusPlus · error
上游 Base URL 不能为空
Error message
上游 Base URL 不能为空
What it means
Thrown by validate_upstream in crates/codex-plus-core/src/protocol_proxy.rs when a relay about to serve a proxied request has an empty (or whitespace-only) base_url. The check runs for every candidate in the rotation — the selected relay, aggregate members, probe selections, and model-route targets — so any candidate with a blank base URL aborts the request before it is tried.
Source
Thrown at crates/codex-plus-core/src/protocol_proxy.rs:1008
api_key: &str,
is_stream: bool,
upstream_body: &Value,
) -> reqwest::RequestBuilder {
let mut builder = client
.post(endpoint)
.bearer_auth(api_key)
.header(reqwest::header::CONTENT_TYPE, "application/json");
if is_stream {
builder = builder
.header(reqwest::header::ACCEPT, "text/event-stream")
.header(reqwest::header::CACHE_CONTROL, "no-cache");
}
builder.json(upstream_body)
}
fn validate_upstream(relay: &crate::settings::RelayProfile) -> anyhow::Result<()> {
if relay.base_url.trim().is_empty() {
anyhow::bail!("上游 Base URL 不能为空");
}
if relay.api_key.trim().is_empty() {
anyhow::bail!("上游 Key 不能为空");
}
Ok(())
}
fn conversation_id_from_responses_request(body: &Value) -> Option<String> {
for key in ["conversation", "conversation_id", "previous_response_id"] {
if let Some(value) = body.get(key).and_then(Value::as_str) {
let value = value.trim();
if !value.is_empty() {
return Some(value.to_string());
}
}
}
None
}View on GitHub (pinned to 1f431ae49b)
Solutions
- Identify which relay failed (the diagnostic log entry protocol_proxy.upstream_request names relayId/relayName) and fill in its base URL
- Audit every member of the active aggregate and remove placeholder profiles that have no base_url
- Save-time validation in the manager: refuse to add a member whose base_url or api_key is empty
Defensive patterns
Strategy: validation
Validate before calling
fn all_candidates_have_base_url(settings: &BackendSettings) -> bool {
settings
.relay_profiles
.iter()
.filter(|p| settings
.active_aggregate_relay_profile()
.map(|a| a.members.iter().any(|m| m.relay_id == p.id))
.unwrap_or(p.id == settings.active_relay_id))
.all(|p| !p.base_url.trim().is_empty())
} Prevention
- Validate base_url is non-empty for every profile when saving settings
- Reject aggregate members referencing profiles without a base URL
- Use the diagnostic log (protocol_proxy.upstream_request) to identify the offending relayId quickly
When it happens
Trigger: An aggregate member relay profile with an empty base_url is selected by rotation; the single active relay never had base_url set; a model-route target profile lost its base_url after an import or hand edit.
Common situations: Aggregate pools containing a placeholder member added but never configured; settings.json edited manually blanking the field; profiles created by duplication where the URL was cleared.
Related errors
- 未找到可用的聚合供应商成员
- Chat Completions 上游 Base URL 不能为空
- 上游 Key 不能为空
- 模型路由目标不能是聚合供应商:{}
- Chat Completions 上游 Key 不能为空
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/04b414888a04c2d6.
Report an issue: GitHub.