{"record":{"id":"b7be6d9e52d7081f","repo":"paperclipai/paperclip","slug":"codex-startup-trust-cannot-preserve-configuration","errorCode":"codex_startup_trust_cannot_preserve_configuration","errorMessage":"codex_startup_trust_cannot_preserve_configuration","messagePattern":"codex_startup_trust_cannot_preserve_configuration","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/codex/codex-startup-trust.ts","lineNumber":52,"sourceCode":"  // An existing project table may not yet have a trust field.\n  for (const match of source.matchAll(/^[ \\t]*\\[(?!\\[)[^\\r\\n]*\\][^\\r\\n]*(?:\\r?\\n|$)/gm)) {\n    const end = match.index! + match[0].length;\n    const candidate = source.slice(0, end) + '\\ntrust_level = \"trusted\"\\n' + source.slice(end);\n    if (matches(candidate)) return candidate;\n  }\n  // Inline project tables are closed to appended table headers. Insert only\n  // when reparsing proves this is the intended object, not a brace in text.\n  const fields = ['trust_level = \"trusted\"', `${JSON.stringify(root)} = { trust_level = \"trusted\" }`];\n  for (const match of source.matchAll(/\\{/g)) {\n    const end = match.index! + 1;\n    for (const field of fields) {\n      for (const separator of [', ', '']) {\n        const candidate = source.slice(0, end) + field + separator + source.slice(end);\n        if (matches(candidate)) return candidate;\n      }\n    }\n  }\n  throw new Error(\"codex_startup_trust_cannot_preserve_configuration\");\n}\n\n/** Run on the execution host, before the provider process loads project config. */\nexport function trustCodexStartupRoot(codexHome: string, cwd: string): void {\n  if (!isAbsolute(codexHome) || !isAbsolute(cwd))\n    throw new Error(\"codex_startup_trust_requires_absolute_paths\");\n  const startup = realpathSync(cwd);\n  let root = startup;\n  try {\n    const top = execFileSync(\n      \"git\",\n      [\"-C\", startup, \"rev-parse\", \"--show-toplevel\"],\n      { encoding: \"utf8\", timeout: 5000, stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n    ).trim();\n    const common = execFileSync(\n      \"git\",\n      [\n        \"-C\",","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/codex/codex-startup-trust.ts#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (config.toml)\n[[projects]]\npath = \"/repo\"\ntrust_level = \"untrusted\"\n// after (config.toml)\n[projects.\"/repo\"]\ntrust_level = \"trusted\"","handlingStrategy":"try-catch","validationCode":"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');","typeGuard":"function isTrustEditFailure(e: unknown): boolean { return e instanceof Error && e.message === 'codex_startup_trust_cannot_preserve_configuration'; }","tryCatchPattern":"try { trustCodexStartupRoot(codexHome, cwd); } catch (e) { if (isTrustEditFailure(e)) { normalizeConfigToml(codexHome); trustCodexStartupRoot(codexHome, cwd); } else throw e; }","preventionTips":["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"],"tags":["toml","config","codex","filesystem"],"backgroundTag":"invalid-config-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}