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

  1. Inspect ~/.codex/config.toml and normalize the projects section to standard tables: [projects."/abs/path"] with trust_level = "trusted".
  2. Back up and simplify the file — remove array-of-tables ([[projects]]) or dotted-key project entries that block in-place editing.
  3. Move unrelated exotic formatting (multiline strings near the projects section) into a separate included file if the Codex version supports it.
  4. Upgrade paperclip-runner: newer versions may add edit strategies for the new config schema.
  5. 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

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


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/b7be6d9e52d7081f. Report an issue: GitHub.