paperclipai/paperclip · error

decision predicate exited 0 (expected 10, 20, or 22)

Error message

${options.errorLabel} decision predicate exited 0 (expected 10, 20, or 22)

What it means

The codex auth merge decision delegates to an external predicate script that must exit 10, 20, or 22 to signal its decision. If execFile resolves with exit code 0, the predicate violated its contract, so the wrapper fails loudly rather than guessing a merge decision. This is an internal invariant check on the predicate protocol.

Solutions

  1. Inspect/repair the predicate script so every path exits 10, 20, or 22.
  2. Check PATH/shims for a shadowing binary and run the intended predicate directly.
  3. Run the predicate manually with the same args to see why it exits 0.
  4. Pin/restore the expected predicate version shipped with the adapter.

Example fix

// before (predicate script)
main();
// after
main().then(code => process.exit(code)).catch(err => { console.error(err); process.exit(1); });
Defensive patterns

Strategy: try-catch

Validate before calling

const r = cp.spawnSync(predicatePath, args);
if (r.status === 0) throw new Error("predicate exited 0; expected 10/20/22");

Try / catch

try { decision = await decideCodexAuthMerge(opts); } catch (e) {
  if (e.message.includes("exited 0")) { console.error("predicate contract violated — check PATH and script version"); }
  throw e;
}

Prevention

When it happens

Trigger: decideCodexAuthMerge runs the decision predicate and it exits 0 — e.g. the script was replaced by a stub, a bug added an early successful return, or the wrong binary is on PATH.

Common situations: A local patch or wrapper script around the predicate swallows the exit code; predicate updated/renamed so a different binary (e.g. a shell no-op) is found first; refactor removed the explicit exit(10/20/22) call paths.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/78d8b12050be3ed8. Report an issue: GitHub.

Appendix: source

Thrown at packages/adapters/codex-local/src/server/codex-auth-merge-decision.ts:77

    await execFile("node", args);
  } catch (error) {
    const code = (error as { code?: unknown }).code;
    if (typeof code === "number" && KNOWN_EXIT_CODES.has(code)) {
      return code;
    }
    const detail =
      typeof code === "string"
        ? `node could not be executed (${code})`
        : typeof code === "number"
          ? `unexpected predicate exit code ${code}`
          : error instanceof Error
            ? error.message
            : String(error);
    throw new Error(`${options.errorLabel} decision predicate failed: ${detail}`);
  }
  // `execFile` resolved, so the predicate exited 0. The predicate always exits
  // 10, 20, or 22, so a clean exit 0 is unexpected; fail loud.
  throw new Error(
    `${options.errorLabel} decision predicate exited 0 (expected 10, 20, or 22)`,
  );
}

View on GitHub (pinned to 3f1d897a7c)