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
- 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)
- Round-trip check before retrying: python3 -c "import tomllib;tomllib.load(open('config.toml','rb'))" or taplo lint
- 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
- Validate config.toml (taplo lint / python tomllib) after every manual edit
- Let codex CLI commands edit marketplaces so writes round-trip through toml_edit instead of hand edits
- Never leave merge-conflict markers or duplicate keys in config.toml
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
- InvalidData
- failed to parse cloud config fragment {fragment}: {message}
- invalid cloud config fragment {fragment}: {message}
- invalid rules in requirements (set by {requirement_source}):
- invalid requirement for MCP server `{server_name}` (set by {
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/ebf4a2f1863a4af6.
Report an issue: GitHub.