BigPizzaV3/CodexPlusPlus · error
config.toml TOML parse failed: {error}
Error message
config.toml TOML parse failed: {error} What it means
Thrown by parse_toml_document in crates/codex-plus-core/src/plugin_marketplace.rs when the config.toml text it is asked to edit cannot be parsed by toml_edit. The function is tolerant of a leading UTF-8 BOM (stripped via trim_start_matches('\u{feff}')) and of empty/whitespace-only files (those yield a fresh empty document), so this error means genuine TOML syntax errors: unclosed strings or tables, duplicate keys, or malformed inline values. The {error} placeholder carries toml_edit's message, which includes the line/column of the offending token.
Source
Thrown at crates/codex-plus-core/src/plugin_marketplace.rs:732
}
fn windows_extended_path(path: &Path) -> String {
let value = path.to_string_lossy();
if value.starts_with(r"\\?\") {
value.into_owned()
} else {
format!(r"\\?\{value}")
}
}
fn parse_toml_document(contents: &str) -> anyhow::Result<DocumentMut> {
let contents = contents.trim_start_matches('\u{feff}');
if contents.trim().is_empty() {
Ok(DocumentMut::new())
} else {
contents
.parse::<DocumentMut>()
.map_err(|error| anyhow::anyhow!("config.toml TOML parse failed: {error}"))
}
}
fn table_mut_or_insert<'a>(doc: &'a mut DocumentMut, key: &str) -> anyhow::Result<&'a mut Table> {
if !doc.as_table().contains_key(key) {
doc[key] = toml_edit::table();
}
if doc.get(key).and_then(Item::as_table).is_none() {
doc[key] = toml_edit::table();
}
doc.get_mut(key)
.and_then(Item::as_table_mut)
.ok_or_else(|| anyhow::anyhow!("{key} must be a TOML table"))
}
fn ensure_trailing_newline(mut contents: String) -> String {
if !contents.ends_with('\n') {
contents.push('\n');View on GitHub (pinned to 1f431ae49b)
Solutions
- Read the {error} suffix: toml_edit reports the exact line and column — open config.toml and fix the syntax at that position
- Validate the file externally before retrying, e.g. cargo toml2json or python -c "import tomllib;tomllib.load(open('config.toml','rb'))" to confirm it parses
- Remove merge-conflict markers and duplicate table/key definitions, and quote any value containing special characters
- If the file is unrecoverable, restore from the backup the tool writes next to it (or regenerate the file) instead of editing the broken one
Example fix
# before (config.toml, broken TOML) model = gpt-5 # unquoted value with a dash [profiles.x key = "unterminated # after model = "gpt-5" [profiles.x] key = "terminated"
Defensive patterns
Strategy: validation
Validate before calling
fn config_toml_parses(path: &Path) -> bool {
let text = std::fs::read_to_string(path)
.unwrap_or_default()
.trim_start_matches('\u{feff}')
.to_string();
text.trim().is_empty()
|| text.parse::<toml_edit::DocumentMut>().is_ok()
} Try / catch
let doc = parse_toml_document(&contents)
.with_context(|| format!("config.toml is invalid — fix the syntax at the reported line, or restore {}", path.display()))?; Prevention
- Run a TOML linter on config.toml after every manual edit
- Resolve git merge conflicts in config.toml completely before launching the app
- Quote all string values and avoid duplicate table headers
When it happens
Trigger: Calling the marketplace/config writer on a hand-edited ~/.codex/config.toml that contains a syntax error (e.g. an unterminated string, a duplicate [profiles.x] header, or a bare value like key = no-quotes); feeding config.toml content that was mangled by a merge conflict; a file truncated mid-write by a crash.
Common situations: Users hand-editing config.toml and introducing typos; git merge conflict markers (<<<<<<<) left in the file; third-party tools rewriting config.toml in a non-TOML-conformant way; CRLF or smart-quote characters pasted from rich-text editors.
Related errors
- {key} must be a TOML table
- {table_name} 必须是 TOML 表
- config.toml TOML 解析失败:{error}
- model_providers.{provider_id} 必须是 TOML table
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/b304c1c7a9f7af41.
Report an issue: GitHub.