BigPizzaV3/CodexPlusPlus · error · anyhow::Error
Base URL 不能为空
Error message
Base URL 不能为空
What it means
fetch_relay_profile_model_ids builds a request source from the RelayProfile, preferring an override base URL but otherwise using upstream_base_url. If the resulting trimmed base_url is empty, no models endpoint can be constructed, so it bails before any network call.
Solutions
- Set upstream_base_url on the RelayProfile (e.g. https://api.example.com) before fetching.
- If the UI is the source, require the Base URL field before enabling the 'fetch models' action.
- Trim-check profile.upstream_base_url client-side and show a validation error instead of calling.
- Re-save the profile ensuring the base URL persisted.
Example fix
// before let ids = fetch_relay_profile_model_ids(&profile).await?; // profile.upstream_base_url == "" // after assert!(!profile.upstream_base_url.trim().is_empty()); let ids = fetch_relay_profile_model_ids(&profile).await?;
Defensive patterns
Strategy: validation
Validate before calling
fn can_fetch_models(profile: &RelayProfile) -> bool {
!profile.upstream_base_url.trim().is_empty()
} Try / catch
if profile.upstream_base_url.trim().is_empty() {
ui.require_field("Base URL");
} else {
match fetch_relay_profile_model_ids(&profile).await { /* ... */ }
} Prevention
- Make Base URL a required field in the profile form
- Disable fetch-models button until base URL is non-empty
- Validate on profile save, not just at fetch time
- Trim and normalize the URL when persisting the profile
When it happens
Trigger: Calling fetch_relay_profile_model_ids with a profile whose upstream_base_url (and any override) is empty or whitespace-only.
Common situations: Profile created but upstream URL never filled in; URL field cleared in the manager UI; profile loaded from an old/partial config file missing the field.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/fbb5791992d3d260.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/model_catalog.rs:721
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 b1ed92e5e4)