paperclipai/paperclip · error · Error

Fake setup session cannot be captured from status ${state.st

Error message

Fake setup session cannot be captured from status ${state.status}.

What it means

Thrown by onEnvironmentCaptureTemplate() after the setup session was located, but its status is one of cancelled, timed_out, or failed. Capturing a template requires a session in an active state (e.g. waiting_for_user, capturing); a terminal-failure session cannot be promoted into a snapshot. The offending status is interpolated into the message.

Source

Thrown at packages/plugins/paperclip-plugin-fake-sandbox/src/plugin.ts:431

        metadata: {
          provider: "fake-plugin",
          found: false,
        },
      };
    }
    return presentSetupSession(state, { includeConnectionPayload: params.includeConnectionPayload === true });
  },

  async onEnvironmentCaptureTemplate(
    params: PluginEnvironmentCaptureTemplateParams,
  ): Promise<PluginEnvironmentCaptureTemplateResult> {
    const config = parseConfig(params.config);
    const state = params.providerLeaseId ? setupSessions.get(params.providerLeaseId) : undefined;
    if (!state) {
      throw new Error("Fake setup session not found.");
    }
    if (state.status === "cancelled" || state.status === "timed_out" || state.status === "failed") {
      throw new Error(`Fake setup session cannot be captured from status ${state.status}.`);
    }

    state.status = "capturing";
    const templateRef = buildTemplateRef(state.environmentId, state.sessionId);
    const template: FakeTemplateState = {
      templateRef,
      environmentId: state.environmentId,
      sessionId: state.sessionId,
      image: config.image,
      sourceTemplateRef: params.sourceTemplateRef ?? state.sourceTemplateRef,
      previousTemplateRef: params.previousTemplateRef ?? null,
      deleted: false,
    };
    templates.set(templateRef, template);
    state.status = "promoted";
    state.capturedTemplateRef = templateRef;
    await removeLease(state.providerLeaseId);

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Start a fresh interactive setup session via onEnvironmentStartInteractiveSetup() and capture from that new lease.
  2. Inspect the session status via onEnvironmentGetInteractiveSetup() before attempting capture; abort if status is terminal.
  3. Fix the test/caller ordering so capture is attempted only on a live session.

Example fix

// before
await plugin.onEnvironmentCancelInteractiveSetup({ providerLeaseId, reason: "user_cancelled" });
await plugin.onEnvironmentCaptureTemplate({ providerLeaseId, ... });
// after
const session = await plugin.onEnvironmentStartInteractiveSetup({ environmentId, sessionId, ... });
await plugin.onEnvironmentCaptureTemplate({ providerLeaseId: session.providerLeaseId, ... });
Defensive patterns

Strategy: validation

Validate before calling

const TERMINAL = new Set(["cancelled", "timed_out", "failed"]);
const session = await plugin.onEnvironmentGetInteractiveSetup({ providerLeaseId });
if (!session || session.status === "missing" || TERMINAL.has(session.status)) {
  // start a new session instead of capturing
}

Type guard

function isCapturableStatus(status: string): boolean {
  return !["cancelled", "timed_out", "failed", "missing"].includes(status);
}

Try / catch

try {
  await plugin.onEnvironmentCaptureTemplate({ providerLeaseId, ... });
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Fake setup session cannot be captured")) {
    // open a fresh session and retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling captureTemplate after onEnvironmentCancelInteractiveSetup() already moved the session to cancelled. Calling capture after the session timed out (reason "timed_out") or failed. A test sequenced cancel-before-capture.

Common situations: Test ordering bug where cancel precedes capture. Real-world flow where a setup timed out and the caller still tried to snapshot it. Reusing a session id after an explicit cancellation.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/97358443e9d45a3b. Report an issue: GitHub.