BigPizzaV3/CodexPlusPlus · error

config.toml TOML 解析失败:

Error message

config.toml TOML 解析失败:{error}

What it means

The settings loader strips a BOM and, if the file is non-empty, parses config.toml into a toml_edit DocumentMut. A syntactically invalid TOML file raises this error, embedding the parser's diagnostic. Unlike empty files (treated as an empty document), any parse error is fatal so corrupted configs are not silently rewritten.

Solutions

  1. Read the embedded {error} message for the exact line/column, then fix that syntax in config.toml.
  2. Validate the file with a TOML linter or paste it into a TOML validator before saving.
  3. Restore config.toml from a backup or regenerate it via the manager UI.
  4. Check for BOM/encoding issues or truncated writes (file ends mid-statement) and rewrite the file cleanly.

Example fix

// before (config.toml)
model = "gpt-5
model_providers = [unclosed
// after
model = "gpt-5"
model_providers = []
Defensive patterns

Strategy: validation

Validate before calling

// Validate TOML before handing it to the settings API
const toml = require('toml');
function isValidToml(text: string): boolean {
  try { toml.parse(text.replace(/^\uFEFF/, '')); return true; } catch { return false; }
}

Try / catch

try {
  await api.loadSettings();
} catch (e) {
  if (String(e).startsWith('config.toml TOML 解析失败')) {
    log.error(e); // message embeds exact line/column
    promptConfigRepair();
  } else { throw e; }
}

Prevention

When it happens

Trigger: config.toml contains malformed TOML: unclosed string/bracket, duplicate keys, tab indentation where disallowed, invalid escape sequences, mixed value types on one key, or manual edit typos.

Common situations: Hand-editing config.toml with a plain text editor and breaking syntax; a crashed write leaving a truncated file; copying settings with smart quotes; merging profiles producing duplicate keys.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/23938f3745dd4087. Report an issue: GitHub.

Appendix: source

Thrown at crates/codex-plus-core/src/settings.rs:1665

    })
}

fn active_provider_id(doc: &DocumentMut) -> Option<String> {
    doc.get("model_provider")
        .and_then(Item::as_str)
        .map(str::trim)
        .filter(|provider| !provider.is_empty())
        .map(ToString::to_string)
}

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 解析失败:{error}"))
    }
}

fn settings_to_object(settings: &BackendSettings) -> Map<String, Value> {
    match serde_json::to_value(settings).unwrap_or_else(|_| Value::Object(Map::new())) {
        Value::Object(map) => map,
        _ => Map::new(),
    }
}

fn normalize_settings_config_sections(mut settings: BackendSettings) -> BackendSettings {
    settings.ccs_db_path = settings.ccs_db_path.trim().to_string();
    let (common, extracted_context) =
        split_context_config_sections(&settings.relay_common_config_contents);
    let context = join_config_sections(&[
        settings.relay_context_config_contents.as_str(),
        extracted_context.as_str(),
    ]);

View on GitHub (pinned to b1ed92e5e4)