warpdotdev/warp · error · anyhow::Error

Failed to parse Codex TOML: {e}

Error message

Failed to parse Codex TOML: {e}

What it means

`normalize_codex_toml_to_json` (feature `local_fs`) parses a Codex `config.toml` with `toml::from_str::<toml::Value>` before normalizing `mcp_servers` entries into JSON. This error means the file is not valid TOML syntax at all — it fires at the whole-file parse. Per-entry type mismatches (an entry matching neither Stdio nor Http) are intentionally tolerated later via `filter_map(... .ok())` and do NOT produce this error.

Source

Thrown at app/src/ai/mcp/parsing.rs:159

                JSONTransportType::SSEServer {
                    url,
                    headers: merged_headers,
                }
            }
        }
    }
}

/// Normalizes the contents of a Codex `config.toml` into a JSON string
/// compatible with `ParsedTemplatableMCPServerResult::from_user_json`.
#[cfg(feature = "local_fs")]
pub(crate) fn normalize_codex_toml_to_json(file_contents: &str) -> Result<String, anyhow::Error> {
    // Parse into a raw Value first so we can handle per-entry deserialization failures
    // gracefully. Using HashMap<String, CodexServerEntry> directly would cause the entire
    // parse to fail if any single entry matches neither Stdio nor Http.
    let raw: toml::Value = toml::from_str(file_contents)
        .map_err(|e| anyhow::anyhow!("Failed to parse Codex TOML: {e}"))?;

    let out_servers: HashMap<String, JSONMCPServer> = raw
        .get("mcp_servers")
        .and_then(|v| v.as_table())
        .map(|table| {
            table
                .iter()
                .filter_map(|(name, val)| {
                    val.clone()
                        .try_into::<CodexServerEntry>()
                        .ok()
                        .map(|entry| {
                            (
                                name.clone(),
                                JSONMCPServer {
                                    transport_type: JSONTransportType::from(entry),
                                },
                            )

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Validate the file with a TOML linter/editor with TOML LSP — the wrapped {e} includes the line/column of the syntax error
  2. Fix common TOML mistakes: quote string values, use [mcp_servers.name] tables, close all brackets and strings
  3. Restore from backup or re-create the file if it was truncated by a concurrent write
  4. Write config files atomically (temp file + rename) so watchers never observe partial content

Example fix

# before (invalid TOML: unquoted command, stray trailing token)
[mcp_servers.fetch]
command = npx
args = [-y, fetch-mcp]  extra

# after
[mcp_servers.fetch]
command = "npx"
args = ["-y", "fetch-mcp"]
Defensive patterns

Strategy: validation

Validate before calling

// Validate TOML before normalizing; surface the span to the user instead of failing late.
if let Err(e) = toml::from_str::<toml::Value>(&file_contents) {
    let offset = e.span().map(|s| s.start).unwrap_or(0);
    return Err(anyhow!("config.toml is invalid TOML near offset {offset}: {e}"));
}

Type guard

fn is_valid_toml(contents: &str) -> bool {
    toml::from_str::<toml::Value>(contents).is_ok()
}

Try / catch

match normalize_codex_toml_to_json(&file_contents) {
    Ok(json) => json,
    Err(e) if e.to_string().contains("Failed to parse Codex TOML") => {
        // surface as a per-file config diagnostic and skip this provider
        diagnostics.push(FileMCPConfigDiagnostic { kind: Parse, message: e.to_string(), .. });
        continue;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: The Codex config file has a TOML syntax error: unclosed table or string, duplicate keys, missing `=` or quotes, malformed arrays/indentation, a BOM, or a truncated file read mid-write by the file watcher.

Common situations: Hand-editing config.toml and leaving a syntax mistake; pasting JSON (not TOML) into config.toml; two tools writing the file concurrently so the watcher reads a half-written file; tabs breaking multiline arrays.

Understand the failure class

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/0915de69a6a60195. Report an issue: GitHub.