paperclipai/paperclip · error · Error

native_execution_input_persisted_binding_mismatch

native_execution_input_persisted_binding_mismatch

Error message

native_execution_input_persisted_binding_mismatch

What it means

prepareNativeSessionBootstrapPersistence compares the run's persisted runnerProfileJson.nativeExecutionInput against the execution input currently being persisted. Once a run has recorded its native execution input (prompt model, cwd, settings, etc.), that binding is immutable. This error means the caller is trying to bind a different native execution configuration to a run that already has one.

Solutions

  1. Ensure input.execution matches the persisted profile exactly; reuse the run's existing nativeExecutionInput when re-invoking.
  2. Start a new run when the execution input (prompt, cwd, model) differs instead of rebinding the existing run.
  3. Normalize/validate the execution object before comparison so key ordering and optional fields serialize identically.
  4. Inspect the run's runnerProfileJson to see the stored binding and reconcile the caller with it.

Example fix

// before
prepareNativeSessionBootstrapPersistence(db, { run, selectedSessionId, execution: { prompt, cwd, settings: newSettings }, restoringCheckpoint: false });
// after
const execution = parseNativeExecutionInput(record(run.runnerProfileJson).nativeExecutionInput) ?? { prompt, cwd, settings: newSettings };
prepareNativeSessionBootstrapPersistence(db, { run, selectedSessionId, execution, restoringCheckpoint: false });
Defensive patterns

Strategy: validation

Validate before calling

function matchesPersistedExecution(run, execution) {
  const profile = record(run.runnerProfileJson);
  if (profile.nativeExecutionInput === undefined) return true;
  return isDeepStrictEqual(parseNativeExecutionInput(profile.nativeExecutionInput), execution);
}

Type guard

const isCompatibleRun = (run, execution) => record(run.runnerProfileJson).nativeExecutionInput === undefined || isDeepStrictEqual(parseNativeExecutionInput(record(run.runnerProfileJson).nativeExecutionInput), execution);

Try / catch

try {
  await prepareNativeSessionBootstrapPersistence(db, { run, selectedSessionId, execution, restoringCheckpoint });
} catch (e) {
  if (e.message === "native_execution_input_persisted_binding_mismatch") {
    // rebind onto a fresh run with the new execution input
    return createRunWithExecution(execution);
  }
  throw e;
}

Prevention

When it happens

Trigger: prepareNativeSessionBootstrapPersistence is called and profile.nativeExecutionInput !== undefined while isDeepStrictEqual(parseNativeExecutionInput(profile.nativeExecutionInput), input.execution) is false — i.e., the run row already stores a nativeExecutionInput that deep-inequality-compares with the supplied execution object.

Common situations: Re-running bootstrap with changed prompt/model/cwd/settings for the same run; resuming a run with execution input serialized in a different key order or with extra fields; passing a different run row that was bootstrapped for a different execution; a code change altering the NativeExecutionInput shape so deep-equality breaks against old persisted profiles.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at server/src/services/native-runtime/native-session-resume.ts:286

      nativeSessionId: string | null;
    };
    selectedSessionId: string;
    execution: NativeExecutionInput;
    restoringCheckpoint: boolean;
  },
) {
  const hasProviderEvents = (
    await nativeSessionProviderEvidence(db, [input.run.id])
  ).has(input.run.id);
  const profile = record(input.run.runnerProfileJson);
  if (
    profile.nativeExecutionInput !== undefined &&
    !isDeepStrictEqual(
      parseNativeExecutionInput(profile.nativeExecutionInput),
      input.execution,
    )
  ) {
    throw new Error("native_execution_input_persisted_binding_mismatch");
  }
  if (
    input.restoringCheckpoint &&
    !isUnusedNativeSessionBootstrap(input.run, hasProviderEvents)
  ) {
    throw new Error("native_session_bootstrap_identity_conflict");
  }
  return nativeSessionIdForBootstrapPersistence({
    ...input,
    hasProviderEvents,
  });
}

/**
 * Legacy compatibility is deliberately narrower than ordinary task-session
 * continuation: only a replacement row that never acquired any native process
 * or provider authority may be rebound to a terminal native source. The exact
 * checkpoint/session/workspace/provider binding is validated separately by

View on GitHub (pinned to 3f1d897a7c)