BigPizzaV3/CodexPlusPlus · error
Grok 模型 不能同时替换并移除 API Key
Error message
Grok 模型 {alias} 不能同时替换并移除 API Key What it means
A model entry may either replace the API key (api_key_update non-empty) or mark it for removal (remove_api_key = true), but not both. validate_request rejects the combination because the two operations are contradictory — there is no defined outcome for 'set this key and remove it'.
Solutions
- Set remove_api_key = false and keep api_key_update with the new key to rotate
- Clear api_key_update (empty string) and keep remove_api_key = true to delete the key
- Reset the form state so only one of the two fields is ever populated
Example fix
// before remove_api_key: true, api_key_update: "sk-new" // after remove_api_key: false, api_key_update: "sk-new"
Defensive patterns
Strategy: validation
Validate before calling
assert!(!(req.remove_api_key && !req.api_key_update.is_empty()), "cannot replace and remove the key at once");
Prevention
- Make replace/remove a single mutually exclusive radio choice in the UI
- Clear related fields when toggling remove_api_key
- Centralize request-building so the invariant is checked in one place
When it happens
Trigger: save_grok_config_at called with input.remove_api_key == true AND input.api_key_update non-empty, typically when a UI checkbox is left checked while a new key is also typed in, or when merging request objects.
Common situations: Editing a model to rotate the key while the 'remove key' toggle from a previous edit is still on; JSON merge patches layering both fields; scripted updates that always set both fields.
Related errors
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/da87f5129debaa88.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/grok_config.rs:305
bail!("Grok 模型来源别名重复:{source}");
}
if !matches!(
input.api_backend.trim(),
"responses" | "chat_completions" | "messages"
) {
bail!("Grok 模型 {alias} 的 API 协议无效");
}
if input.context_window == Some(0) {
bail!("Grok 模型 {alias} 的上下文窗口必须大于 0");
}
if input
.context_window
.is_some_and(|value| value > i64::MAX as u64)
{
bail!("Grok 模型 {alias} 的上下文窗口过大");
}
if input.remove_api_key && !input.api_key_update.is_empty() {
bail!("Grok 模型 {alias} 不能同时替换并移除 API Key");
}
}
Ok(())
}
fn table_string(doc: &DocumentMut, table: &str, key: &str) -> String {
doc.get(table)
.and_then(Item::as_table_like)
.and_then(|values| values.get(key))
.and_then(Item::as_str)
.unwrap_or_default()
.to_string()
}
fn item_string<T: TableLike + ?Sized>(table: &T, key: &str) -> String {
table
.get(key)
.and_then(Item::as_str)View on GitHub (pinned to b1ed92e5e4)