{"record":{"id":"684f1b8d75003fc6","repo":"BigPizzaV3/CodexPlusPlus","slug":"config-toml-toml-error","errorCode":null,"errorMessage":"config.toml TOML 解析失败：{error}","messagePattern":"config\\.toml TOML 解析失败：(.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/relay_config.rs","lineNumber":1284,"sourceCode":"fn is_custom_provider_id(provider: &str) -> bool {\n    !provider.is_empty() && !RESERVED_MODEL_PROVIDER_IDS.contains(&provider)\n}\n\nfn provider_table_exists(doc: &DocumentMut, provider_id: &str) -> bool {\n    doc.get(\"model_providers\")\n        .and_then(Item::as_table)\n        .and_then(|table| table.get(provider_id))\n        .is_some()\n}\n\nfn parse_toml_document(contents: &str) -> anyhow::Result<DocumentMut> {\n    let contents = contents.trim_start_matches('\\u{feff}');\n    if contents.trim().is_empty() {\n        Ok(DocumentMut::new())\n    } else {\n        contents\n            .parse::<DocumentMut>()\n            .map_err(|error| anyhow::anyhow!(\"config.toml TOML 解析失败：{error}\"))\n    }\n}\n\nfn remove_provider_specific_common_keys(table: &mut dyn TableLike) {\n    for key in PROVIDER_SPECIFIC_COMMON_ROOT_KEYS {\n        table.remove(key);\n    }\n    let sensitive_keys: Vec<String> = table\n        .iter()\n        .map(|(key, _)| key.to_string())\n        .filter(|key| is_provider_credential_root_key(key))\n        .collect();\n    for key in sensitive_keys {\n        table.remove(&key);\n    }\n    table.remove(\"model_providers\");\n}\n","sourceCodeStart":1266,"sourceCodeEnd":1302,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/relay_config.rs#L1266-L1302","documentation":"parse_toml_document 是库内所有 TOML 解析的统一出口：剥 BOM、空文本返回空 Document，否则用 toml_edit 解析，失败时把 toml_edit 的错误信息（含行号/列号）包进「config.toml TOML 解析失败：{error}」。任何 config 文本入口（apply_context_limits、upsert_context_entry、set_experimental_bearer_token 等）解析失败都会冒出此错误。","triggerScenarios":"传入的 config.toml 文本有语法错误：未闭合的引号/括号、重复键、非法字符、把字符串值写成裸 token、表头格式错误等。错误串中 {error} 部分带具体行列位置。","commonSituations":"手工编辑 config.toml 引入语法错误；用字符串拼接生成 TOML 而未转义；粘贴含全角引号/中文标点的配置；上游其他工具写坏的 config 被 backfill 读回再重新解析。","solutions":["按错误信息中的行列号定位并修复语法","用 TOML linter / 编辑器语法高亮校验后再提交","调用前先 toml::from_str::<toml::Value>(text) 自检，给用户即时的编辑器反馈"],"exampleFix":"# before\nmodel_provider = \"openrouter\nmodel = \"gpt-5\"\n\n# after\nmodel_provider = \"openrouter\"\nmodel = \"gpt-5\"","handlingStrategy":"validation","validationCode":"fn validate_toml(text: &str) -> anyhow::Result<()> {\n    let text = text.trim_start_matches('\\u{feff}');\n    if !text.trim().is_empty() {\n        text.parse::<toml_edit::DocumentMut>()\n            .map_err(|e| anyhow::anyhow!(\"config.toml TOML 解析失败：{e}\"))?;\n    }\n    Ok(())\n}\n// 提交前调用，可拿到与库一致的行列错误信息","typeGuard":null,"tryCatchPattern":"match apply_relay_config_file_to_home(&home, &contents) {\n    Ok(r) => {}\n    Err(err) if err.to_string().contains(\"TOML 解析失败\") => {\n        // 把 {error} 里的行列信息透传给编辑器定位，不让用户重试同一份坏文本\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["编辑器侧接入实时 TOML 校验（toml_edit 解析一次即可）","拼接生成 TOML 时用 toml_edit 构建而非字符串相加","粘贴配置后先高亮校验再保存"],"tags":["toml","parse-error","config-toml"],"backgroundTag":"toml-parse-error","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}