BigPizzaV3/CodexPlusPlus · error
中转 Key 不能为空
Error message
中转 Key 不能为空
What it means
Thrown by `apply_relay_config_to_home_with_session_provider` in relay_config.rs when `bearer_token` is empty after trimming. The token becomes the API key written into config.toml/auth for the relay provider; without it codex could not authenticate. The check runs after base_url validation and before the session-provider/protocol compatibility check.
Solutions
- Provide the relay bearer token / API key as the bearer_token argument.
- Resolve the key from a secret store or env var and assert it is non-empty before applying.
- Gate the apply action in the UI on a non-empty key field.
Example fix
// before
let token = std::env::var("RELAY_KEY").unwrap_or_default();
apply_relay_config_to_home_with_protocol(home, url, &token, ...).await?;
// after
let token = std::env::var("RELAY_KEY").context("RELAY_KEY not set")?;
apply_relay_config_to_home_with_protocol(home, url, &token, ...).await?; Defensive patterns
Strategy: validation
Validate before calling
let token = bearer_token.trim(); anyhow::ensure!(!token.is_empty(), "中转 Key 不能为空");
Type guard
fn has_token(t: &str) -> bool { !t.trim().is_empty() } Try / catch
match apply_relay_config_to_home_with_protocol(home, url, key, proto, port, sp).await {
Ok(r) => Ok(r),
Err(e) if e.to_string().contains("中转 Key 不能为空") => Err(anyhow::anyhow!("请先在中转站设置中填写 API Key")),
Err(e) => Err(e),
} Prevention
- Fetch keys from a secret manager with a hard error instead of empty fallback.
- Keep key and profile validation together in one pre-apply check function.
- In UIs, disable apply while the key field is blank.
When it happens
Trigger: Calling `apply_relay_config_to_home_with_protocol` with a valid base_url but `bearer_token = ""` or whitespace; bails at relay_config.rs:405.
Common situations: Profile stored without a key (user chose 'fill later'); env var holding the token unset at apply time; token cleared by an edit in the manager UI but apply still invoked.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
Related errors
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/8f4b908dcdb94e08.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/relay_config.rs:405
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_token
}))?;
let backup_path =
write_codex_live_atomic(home, Some(&updated), Some(auth_contents.as_bytes()))?;
let status = relay_config_status_from_home(home);View on GitHub (pinned to b1ed92e5e4)