paperclipai/paperclip · error · Error

Unsupported test-drive harness: ${String(harness)}.

Error message

Unsupported test-drive harness: ${String(harness)}.

What it means

After warm-transition recovery converges (identity matched, transition cleared), the transport verifies that the warm-recovery command actually completed by checking `core.getCommand(warmRecovery.commandId)?.status !== "completed"`. If the command is missing, pending, or failed, the transition result cannot be proven and this error is thrown.

Source

Thrown at cli/src/commands/test-drive.ts:234

    throw new Error(
      "test-drive cannot reuse a data directory configured for an external PostgreSQL database. " +
        "Choose a fresh data directory or change database.mode to embedded-postgres.",
    );
  }
}

export function resolveTestDriveBootstrap(
  options: TestDriveOptions,
  env: NodeJS.ProcessEnv = process.env,
): ResolvedTestDriveBootstrap {
  if (options.apiKey !== undefined && options.apiKeyEnv !== undefined) {
    throw new Error("--api-key and --api-key-env are mutually exclusive.");
  }

  const harness = options.harness ?? "claude";
  const definition = HARNESS_DEFINITIONS[harness];
  if (!definition) {
    throw new Error(`Unsupported test-drive harness: ${String(harness)}.`);
  }

  const companyName = (options.companyName ?? "Test Company").trim();
  const agentName = (options.agentName ?? "CEO").trim();
  if (!companyName) throw new Error("--company-name cannot be empty.");
  if (!agentName) throw new Error("--agent-name cannot be empty.");

  const model = options.model;
  if (model !== undefined && (!model || model.trim() !== model)) {
    throw new Error("--model cannot be empty or have surrounding whitespace.");
  }
  if (
    harness === "opencode" &&
    (!model || !/^openrouter\/[^/\s]+(?:\/[^/\s]+)*$/.test(model))
  ) {
    throw new Error(
      "OpenCode test drives require --model openrouter/<model>, with no empty path segments.",
    );

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check runnerd logs for the fate of the recovery command (did it fail or get dropped?) and fix the root cause before retrying the transition.
  2. Ensure command records are retained in the store until the transition completes.
  3. Re-run the warm transition so a fresh recovery command is issued and completes.

Example fix

// before
// command lost; treat as fatal
if (core.getCommand(id)?.status !== "completed") throw ...;
// after
const cmd = core.getCommand(id);
if (cmd?.status !== "completed") {
  await retryWarmTransition(root, desiredIdentity); // re-issue command
}
Defensive patterns

Strategy: retry

Validate before calling

const cmd = core.getCommand(warmRecovery.commandId);
if (!cmd) throw new Error("recovery command record missing — cannot verify warm transition");

Type guard

function isCompleted(cmd: { status?: string } | undefined): cmd is { status: "completed" } {
  return cmd?.status === "completed";
}

Try / catch

try {
  await transport.startTurn(input);
} catch (e) {
  if (e.message === "native_runner_warm_transition_result_unproven") {
    await retryWarmTransition(root, desiredIdentity); // re-issue the recovery command
  }
}

Prevention

When it happens

Trigger: The recovery command referenced by `warmRecovery.commandId` has any status other than "completed" (including `undefined` — command record not found) after the identity wait loop succeeds.

Common situations: The command record was evicted/pruned from the store before being checked; the command failed but the identity still converged; a race where status is read too early because polling conditions passed on a stale snapshot.

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@01ad858492 (2026-09-10). Data as JSON: /api/errors/63d6ecc786baa0c6. Report an issue: GitHub.