openai/codex · error · std::io::Error

InvalidData

InvalidData

Error message

{}

What it means

remove_user_marketplace_config edits $CODEX_HOME/config.toml through toml_edit so comments and formatting survive the write. Before removing a [marketplaces] entry it parses the whole document; if the file is not valid TOML, the toml_edit::TomlError is wrapped as io::Error(InvalidData) with its message, and the removal aborts rather than rewriting a file the editor cannot faithfully round-trip. A missing file is not an error (it returns the NotFound outcome).

Source

Thrown at codex-rs/config/src/marketplace_edit.rs:52

    upsert_marketplace(&mut doc, marketplace_name, update);
    fs::create_dir_all(codex_home)?;
    fs::write(config_path, doc.to_string())
}

pub fn remove_user_marketplace(codex_home: &Path, marketplace_name: &str) -> std::io::Result<bool> {
    let outcome = remove_user_marketplace_config(codex_home, marketplace_name)?;
    Ok(outcome == RemoveMarketplaceConfigOutcome::Removed)
}

pub fn remove_user_marketplace_config(
    codex_home: &Path,
    marketplace_name: &str,
) -> std::io::Result<RemoveMarketplaceConfigOutcome> {
    let config_path = codex_home.join(CONFIG_TOML_FILE);
    let mut doc = match fs::read_to_string(&config_path) {
        Ok(raw) => raw
            .parse::<DocumentMut>()
            .map_err(|err| std::io::Error::new(ErrorKind::InvalidData, err))?,
        Err(err) if err.kind() == ErrorKind::NotFound => {
            return Ok(RemoveMarketplaceConfigOutcome::NotFound);
        }
        Err(err) => return Err(err),
    };

    let outcome = remove_marketplace(&mut doc, marketplace_name);
    if outcome != RemoveMarketplaceConfigOutcome::Removed {
        return Ok(outcome);
    }

    fs::create_dir_all(codex_home)?;
    fs::write(config_path, doc.to_string())?;
    Ok(RemoveMarketplaceConfigOutcome::Removed)
}

fn read_or_create_document(config_path: &Path) -> std::io::Result<DocumentMut> {
    match fs::read_to_string(config_path) {

View on GitHub (pinned to 339751715c)

Solutions

  1. Open config.toml at the line/column named in the error message and fix the syntax error (unquoted strings and duplicate keys are the usual suspects)
  2. Round-trip check before retrying: python3 -c "import tomllib;tomllib.load(open('config.toml','rb'))" or taplo lint
  3. If the file is unrecoverable, back it up and delete it — removal then returns NotFound instead of an error

Example fix

# before ($CODEX_HOME/config.toml) — unquoted value
[marketplaces.debug]
source_type = git
source = "https://github.com/owner/repo.git"

# after
[marketplaces.debug]
source_type = "git"
source = "https://github.com/owner/repo.git"
Defensive patterns

Strategy: validation

Validate before calling

use std::fs;
use std::io;
use std::path::Path;
use toml_edit::DocumentMut;

// Run before remove_user_marketplace_config so edits never start from a broken file.
fn config_toml_parses(codex_home: &Path) -> io::Result<()> {
    let raw = fs::read_to_string(codex_home.join("config.toml"))?;
    raw.parse::<DocumentMut>()
        .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
    Ok(())
}

Try / catch

match remove_user_marketplace_config(codex_home, name) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
        // e's message embeds the toml_edit parse error with line/column;
        // surface it and have the user fix config.toml before retrying.
    }
    Err(e) => return Err(e),
    Ok(outcome) => match outcome {
        RemoveMarketplaceConfigOutcome::Removed => {}
        RemoveMarketplaceConfigOutcome::NotFound => {}
        RemoveMarketplaceConfigOutcome::NameCaseMismatch { configured_name } => {}
    },
}

Prevention

When it happens

Trigger: Calling remove_user_marketplace or remove_user_marketplace_config while config.toml contains any TOML syntax error — unquoted value, duplicate key, unterminated table or string, or a stray comma in an inline table like `marketplaces = { debug = {...}, }`.

Common situations: Hand-edited config.toml with a typo; leftover git merge-conflict markers; files assembled by concatenating snippets; smart quotes pasted from docs or chat; a truncated file after a previously crashed writer.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/ebf4a2f1863a4af6. Report an issue: GitHub.