paperclipai/paperclip · error
codex_startup_trust_cannot_preserve_configuration
codex_startup_trust_cannot_preserve_configuration
Error message
codex_startup_trust_cannot_preserve_configuration
What it means
editTrust rewrites ~/.codex/config.toml to set trust_level = "trusted" for the project root while preserving every other byte of the file. It tries semantic-preserving edits (append table header, replace existing trust_level value, inject into an existing project table, inject into an inline table) and validates each candidate by re-parsing and deep-comparing against the intended config. If no candidate produces the exact intended document, it throws codex_startup_trust_cannot_preserve_configuration rather than corrupting the user's configuration.
Source
Thrown at packages/paperclip-runner/src/drivers/codex/codex-startup-trust.ts:52
// An existing project table may not yet have a trust field.
for (const match of source.matchAll(/^[ \t]*\[(?!\[)[^\r\n]*\][^\r\n]*(?:\r?\n|$)/gm)) {
const end = match.index! + match[0].length;
const candidate = source.slice(0, end) + '\ntrust_level = "trusted"\n' + source.slice(end);
if (matches(candidate)) return candidate;
}
// Inline project tables are closed to appended table headers. Insert only
// when reparsing proves this is the intended object, not a brace in text.
const fields = ['trust_level = "trusted"', `${JSON.stringify(root)} = { trust_level = "trusted" }`];
for (const match of source.matchAll(/\{/g)) {
const end = match.index! + 1;
for (const field of fields) {
for (const separator of [', ', '']) {
const candidate = source.slice(0, end) + field + separator + source.slice(end);
if (matches(candidate)) return candidate;
}
}
}
throw new Error("codex_startup_trust_cannot_preserve_configuration");
}
/** Run on the execution host, before the provider process loads project config. */
export function trustCodexStartupRoot(codexHome: string, cwd: string): void {
if (!isAbsolute(codexHome) || !isAbsolute(cwd))
throw new Error("codex_startup_trust_requires_absolute_paths");
const startup = realpathSync(cwd);
let root = startup;
try {
const top = execFileSync(
"git",
["-C", startup, "rev-parse", "--show-toplevel"],
{ encoding: "utf8", timeout: 5000, stdio: ["ignore", "pipe", "ignore"] },
).trim();
const common = execFileSync(
"git",
[
"-C",View on GitHub (pinned to 01ad858492)
Solutions
- Inspect ~/.codex/config.toml and normalize the projects section to standard tables: [projects."/abs/path"] with trust_level = "trusted".
- Back up and simplify the file — remove array-of-tables ([[projects]]) or dotted-key project entries that block in-place editing.
- Move unrelated exotic formatting (multiline strings near the projects section) into a separate included file if the Codex version supports it.
- Upgrade paperclip-runner: newer versions may add edit strategies for the new config schema.
- Delete/regenerate config.toml (losing non-trust customization) only as a last resort after backup.
Example fix
// before (config.toml) [[projects]] path = "/repo" trust_level = "untrusted" // after (config.toml) [projects."/repo"] trust_level = "trusted"
Defensive patterns
Strategy: try-catch
Validate before calling
const src = readFileSync(join(codexHome,'config.toml'),'utf8'); if (/\[\[\s*projects/.test(src) || /^\s*projects\s*=\s*\[/m.test(src)) console.warn('config.toml uses array-of-tables/dotted projects; in-place trust edit may fail'); Type guard
function isTrustEditFailure(e: unknown): boolean { return e instanceof Error && e.message === 'codex_startup_trust_cannot_preserve_configuration'; } Try / catch
try { trustCodexStartupRoot(codexHome, cwd); } catch (e) { if (isTrustEditFailure(e)) { normalizeConfigToml(codexHome); trustCodexStartupRoot(codexHome, cwd); } else throw e; } Prevention
- Keep config.toml projects entries as standard tables ([projects."/path"])
- Avoid [[projects]] array-of-tables and dotted-key project entries
- Back up config.toml before hand edits or other-tool writes
- Keep paperclip-runner updated with the Codex config schema
When it happens
Trigger: config.toml contains TOML constructs none of the edit strategies can handle while preserving semantics — e.g. the target project table is inside an array-of-tables ([[projects]]), a dotted-key projects.<path> assignment the regexes miss, or trust_level set in a way that only a full-file rewrite could express.
Common situations: Hand-edited or unusually formatted config.toml; Codex version that changed the trust config schema (e.g. array-of-tables projects); config generated by another tool with exotic formatting that makes in-place edits ambiguous.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- codex_startup_trust_invalid_projects
- codex_startup_trust_invalid_project
- Registered ${label} Paperclip config is missing its adjacent
- Registered base project workspace Paperclip config at ${conf
- ${label} does not exist at ${resolved}.
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/b7be6d9e52d7081f.
Report an issue: GitHub.