{"record":{"id":"978d11e5f2724250","repo":"BigPizzaV3/CodexPlusPlus","slug":"other","errorCode":null,"errorMessage":"未知上下文类型：{other}","messagePattern":"未知上下文类型：(.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/relay_config.rs","lineNumber":1973,"sourceCode":"                toml_body: body,\n                enabled: context_entry_enabled(table),\n            })\n        })\n        .collect()\n}\n\nfn table_body_to_string(table: &Table) -> String {\n    let mut doc = DocumentMut::new();\n    merge_toml_table_like(doc.as_table_mut(), table);\n    normalize_optional_toml(doc)\n}\n\nfn context_table_name(kind: &str) -> anyhow::Result<&'static str> {\n    match kind {\n        \"mcp\" | \"mcpServer\" | \"mcpServers\" => Ok(\"mcp_servers\"),\n        \"skill\" | \"skills\" => Ok(\"skills\"),\n        \"plugin\" | \"plugins\" => Ok(\"plugins\"),\n        other => anyhow::bail!(\"未知上下文类型：{other}\"),\n    }\n}\n\nfn context_kind_name(table: &str) -> &'static str {\n    match table {\n        \"mcp_servers\" => \"mcp\",\n        \"skills\" => \"skill\",\n        \"plugins\" => \"plugin\",\n        _ => \"unknown\",\n    }\n}\n\nfn context_entry_summary(body: &str) -> String {\n    body.lines()\n        .map(str::trim)\n        .find(|line| !line.is_empty() && !line.starts_with('#'))\n        .unwrap_or(\"\")\n        .chars()","sourceCodeStart":1955,"sourceCodeEnd":1991,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/relay_config.rs#L1955-L1991","documentation":"context_table_name 把调用方传入的 kind 字符串映射为 common config 中的表名：mcp/mcpServer/mcpServers -> mcp_servers，skill/skills -> skills，plugin/plugins -> plugins。其他任何值都 bail「未知上下文类型：{other}」。upsert/delete/filter 等所有上下文条目操作都经过此映射。","triggerScenarios":"调用 upsert_context_entry_in_common_config / delete_context_entry_from_common_config / list_context_entries_from_common_config 时 kind 传了受支持别名之外的字符串，例如 \"mcp_servers\"（下划线形式不在别名列表里）、\"tools\"、\"\"。","commonSituations":"前端把自己内部的枚举值（下划线命名）直接透传给后端；新增上下文类型时只改了前端没改这个 match；拼写大小写不一致（只有列出的精确别名被接受）。","solutions":["改用受支持的字面量之一：mcp / mcpServer / mcpServers、skill / skills、plugin / plugins","在前端定义枚举并在序列化层约束取值，避免自由字符串透传","新增类型时同步修改 context_table_name 和 context_kind_name 两个映射"],"exampleFix":"// before\nupsert_context_entry_in_common_config(&common, \"mcp_servers\", \"fetch\", &body)?;\n\n// after\nupsert_context_entry_in_common_config(&common, \"mcp\", \"fetch\", &body)?;","handlingStrategy":"type-guard","validationCode":"const VALID_CONTEXT_KINDS: &[&str] = &[\"mcp\", \"mcpServer\", \"mcpServers\", \"skill\", \"skills\", \"plugin\", \"plugins\"];\nanyhow::ensure!(VALID_CONTEXT_KINDS.contains(&kind), \"未知上下文类型：{kind}\");\nupsert_context_entry_in_common_config(&common, kind, id, body)?;","typeGuard":"fn is_valid_context_kind(kind: &str) -> bool {\n    matches!(kind, \"mcp\" | \"mcpServer\" | \"mcpServers\" | \"skill\" | \"skills\" | \"plugin\" | \"plugins\")\n}","tryCatchPattern":"match upsert_context_entry_in_common_config(&common, kind, id, body) {\n    Ok(c) => common = c,\n    Err(err) if err.to_string().contains(\"未知上下文类型\") => { /* 修正 kind 后重试 */ }\n    Err(err) => return Err(err),\n}","preventionTips":["前端用受控枚举传 kind，禁止自由字符串透传","注意 \"mcp_servers\"（表名）不是合法 kind，合法值是 \"mcp\" 等别名","新增类型时同步维护 context_table_name 的 match 分支"],"tags":["common-config","context-entry","enum","validation"],"backgroundTag":"invalid-enum-value","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}