paperclipai/paperclip · error · Error

Paperclip returned no result while ${action}.

Error message

Paperclip returned no result while ${action}.

What it means

Thrown when a PRP run rotation must be performed without an exact authority match and with no warm recovery available, but the local control-plane state needed to rotate the local authority epoch is missing — either there is no local provider or the tracked controlPlaneState is null. The library cannot rotate an authority epoch from nothing, so it throws.

Source

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

    adapterType: "opencode_local",
    credentialTarget: "OPENROUTER_API_KEY",
    credentialName: "OpenRouter API Key",
  },
};

const NON_PAPERCLIP_ISOLATED_ENV_KEYS = [
  "DATABASE_URL",
  "DATABASE_MIGRATION_URL",
  "HOST",
  "PORT",
  "SERVE_UI",
  "BETTER_AUTH_URL",
  "BETTER_AUTH_BASE_URL",
] as const;

function requiredApiResult<T>(value: T | null, action: string): T {
  if (value === null) {
    throw new Error(`Paperclip returned no result while ${action}.`);
  }
  return value;
}

function errorMessage(error: unknown): string {
  if (error instanceof Error) return error.message || error.name;
  if (typeof error === "string") return error;
  try {
    return JSON.stringify(error);
  } catch {
    return String(error);
  }
}

export function redactTestDriveText(text: string, credentials: Array<string | undefined>): string {
  let redacted = text;
  for (const credential of credentials) {
    if (!credential) continue;

View on GitHub (pinned to 01ad858492)

Solutions

  1. Ensure the local provider is enabled and that control-plane state was loaded before reaching the rotation step.
  2. Use warm recovery (a valid recovery proof/receipt) so the exact-authority path or warm-recovery path can be taken instead of local rotation.
  3. Restore or regenerate the runner's persisted control-plane state so controlPlaneState is non-null at rotation time.

Example fix

// before
// rotation attempted with no prior state loaded
controlPlaneState = rotateLocalAuthorityEpoch(root, null, desiredIdentity, ...);
// after
if (!controlPlaneState) {
  controlPlaneState = await bootstrapControlPlaneState(root, desiredIdentity);
}
controlPlaneState = rotateLocalAuthorityEpoch(root, controlPlaneState, desiredIdentity, ...);
Defensive patterns

Strategy: validation

Validate before calling

const canRotateLocally = Boolean(localProvider) && controlPlaneState !== null;
if (!exactAuthority && warmRecovery === null && !canRotateLocally) {
  throw new Error("cannot rotate authority: no local state and no warm recovery");
}

Type guard

function canRotate(cpState: unknown, hasLocalProvider: boolean): boolean {
  return hasLocalProvider && cpState !== null && typeof cpState === "object";
}

Try / catch

try {
  await transport.start(params);
} catch (e) {
  if (e.message === "native_runner_prp_run_rotation_unavailable") {
    // bootstrap control-plane state, then retry
    await bootstrapControlPlaneState(root, desiredIdentity);
  }
}

Prevention

When it happens

Trigger: Authority identity differs from the current one (exactAuthority is false), warm recovery is unavailable (null), and either `localProvider` is falsy or `controlPlaneState` is null at the rotation point.

Common situations: Restarting a runner against a fresh state file so no prior control-plane state exists; disabling the local provider in configuration while relying on local rotation; corrupted or wiped runner state store losing controlPlaneState.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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