BigPizzaV3/CodexPlusPlus · error · anyhow::Error
Base URL 不能为空
Error message
Base URL 不能为空
What it means
fetch_relay_profile_model_ids (crates/codex-plus-core/src/model_catalog.rs:564) resolves a ModelSource from a RelayProfile: it prefers upstream_base_url when non-blank, otherwise base_url, both trimmed. If the chosen URL is empty it bails with 'Base URL 不能为空' before any network call. This is config validation: the profile exists but has no usable endpoint URL, so the /models fetch for the model catalog cannot even be addressed.
Source
Thrown at crates/codex-plus-core/src/model_catalog.rs:583
profile: &RelayProfile,
) -> anyhow::Result<(Vec<String>, String)> {
let source = ModelSource {
source_id: format!("relay-profile:{}", profile.id),
source_type: "relay_profile".to_string(),
name: if profile.name.trim().is_empty() {
profile.id.clone()
} else {
profile.name.trim().to_string()
},
base_url: if profile.upstream_base_url.trim().is_empty() {
profile.base_url.trim().to_string()
} else {
profile.upstream_base_url.trim().to_string()
},
api_key: profile.api_key.trim().to_string(),
};
if source.base_url.is_empty() {
anyhow::bail!("Base URL 不能为空");
}
let endpoint = models_endpoint(&source.base_url);
let client = crate::http_client::proxied_client(&profile.user_agent)?;
let (models, status) = fetch_models_from_source(&client, &source).await;
if models.is_empty() {
let message = status
.get("message")
.and_then(Value::as_str)
.unwrap_or("上游没有返回可用模型");
anyhow::bail!("{message}");
}
Ok((models, endpoint))
}
fn preferred_responses_api_status(sources: &[Value]) -> Value {
let statuses = sources
.iter()
.filter_map(|source| source.get("responses_api"))View on GitHub (pinned to 1f431ae49b)
Solutions
- Fill in a base URL: set upstream_base_url (preferred) or base_url on the relay profile before refreshing its model list
- Trim and validate before calling: reject blank URLs in the UI/save path so profiles cannot persist without an endpoint
- If the profile is a placeholder, remove or disable it so catalog refresh skips it
- Check both fields — an empty upstream_base_url silently falls back to base_url, so both must be blank to hit this
Example fix
// before
let profile = RelayProfile { name: "demo".into(), ..Default::default() }; // no URLs
let (models, endpoint) = fetch_relay_profile_model_ids(&profile).await?; // bail
// after
let profile = RelayProfile {
name: "demo".into(),
upstream_base_url: "https://api.example.com".into(),
..Default::default()
};
let (models, endpoint) = fetch_relay_profile_model_ids(&profile).await?; Defensive patterns
Strategy: validation
Validate before calling
fn relay_profile_has_base_url(profile: &RelayProfile) -> bool {
let upstream = profile.upstream_base_url.trim();
let base = profile.base_url.trim();
!upstream.is_empty() || !base.is_empty()
}
assert!(relay_profile_has_base_url(&profile)); Type guard
fn usable_base_url(profile: &RelayProfile) -> Option<&str> {
let upstream = profile.upstream_base_url.trim();
let base = profile.base_url.trim();
Some(if upstream.is_empty() { base } else { upstream }).filter(|u| !u.is_empty())
} Try / catch
match fetch_relay_profile_model_ids(&profile).await {
Err(e) if e.to_string().contains("Base URL 不能为空") => {
// config bug: skip profile, surface to user in UI
mark_profile_invalid(&profile.id, "missing base URL");
}
rest => rest?,
} Prevention
- Require a non-blank base URL in the profile save path/UI before persistence
- Trim inputs on save; treat whitespace-only as empty
- When migrating settings, verify every relay profile resolves to a non-empty effective URL
When it happens
Trigger: Calling fetch_relay_profile_model_ids (directly or via the manager's model-list refresh for a relay profile) where the profile's upstream_base_url and base_url are both empty or whitespace-only — e.g. a newly created profile saved before its URL field was filled, or TOML/settings migration wiping the fields.
Common situations: UI flow letting users save a relay profile without a required URL; profiles imported/migrated from older settings versions where the field was named differently; whitespace-only URLs pasted by accident; tests constructing RelayProfile::default()-like values without setting URLs.
Related errors
- 上游没有返回可用模型
- provider sync requires launcher hooks with codex-plus-data i
- Remote Control session recovery requires launcher hooks with
- macOS open command is empty
- Codex command is empty
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/fbb5791992d3d260.
Report an issue: GitHub.