paperclipai/paperclip · error · Error

Sandbox bridge mode requires a host-side Paperclip API token

Error message

Sandbox bridge mode requires a host-side Paperclip API token.

What it means

Thrown by ensureAdapterExecutionTargetPaperclipBridge when the hostApiToken input is null, undefined, empty, or whitespace-only. The Paperclip callback bridge authenticates every sandbox-to-host request with this token, so an absent token makes the bridge non-functional and is rejected before any bridge infrastructure is created.

Source

Thrown at packages/adapter-utils/src/execution-target.ts:2058

  getRuntimeParentContext?: () => StartupSpanContext | undefined;
  // Wrap each callback request in a `sandbox.callbackBridge.relayRequest` span.
  // The factory threads it into the worker, which uses it per request so each
  // request's execs group under one wrapper span. When it is absent, the request
  // work runs under the run parent with no wrapper span.
  runtimeSpan?: RuntimeSpanRunner;
}): Promise<AdapterExecutionTargetPaperclipBridgeHandle | null> {
  if (!adapterExecutionTargetUsesPaperclipBridge(input.target)) {
    return null;
  }
  if (!input.target || input.target.kind !== "remote") {
    return null;
  }

  const target = input.target;
  const onLog = input.onLog ?? (async () => {});
  const hostApiToken = input.hostApiToken?.trim() ?? "";
  if (hostApiToken.length === 0) {
    throw new Error("Sandbox bridge mode requires a host-side Paperclip API token.");
  }

  const runtimeRootDir =
    input.runtimeRootDir?.trim().length
      ? input.runtimeRootDir.trim()
      : path.posix.join(target.remoteCwd, ".paperclip-runtime", input.adapterKey);
  const bridgeRuntimeDir = path.posix.join(runtimeRootDir, "paperclip-bridge");
  const queueDir = path.posix.join(bridgeRuntimeDir, "queue");
  const assetRemoteDir = path.posix.join(bridgeRuntimeDir, "server");
  const bridgeToken = createSandboxCallbackBridgeToken();
  const maxBodyBytes =
    typeof input.maxBodyBytes === "number" && Number.isFinite(input.maxBodyBytes) && input.maxBodyBytes > 0
      ? Math.trunc(input.maxBodyBytes)
      : DEFAULT_SANDBOX_CALLBACK_BRIDGE_MAX_BODY_BYTES;
  const hostApiUrl =
    input.hostApiUrl?.trim() ||
    process.env.PAPERCLIP_RUNTIME_API_URL?.trim() ||
    process.env.PAPERCLIP_API_URL?.trim() ||

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Provide a valid hostApiToken in the ensureAdapterExecutionTargetPaperclipBridge input.
  2. Verify the Paperclip API token is configured in the host process environment or agent configuration.
  3. Check that the token is not being stripped or emptied by an intermediate configuration layer before reaching the bridge setup.

Example fix

// before
await ensureAdapterExecutionTargetPaperclipBridge({
  target,
  adapterKey: "claude",
  hostApiToken: process.env.MAYBE_TOKEN, // undefined when unset
});
// after
await ensureAdapterExecutionTargetPaperclipBridge({
  target,
  adapterKey: "claude",
  hostApiToken: process.env.PAPERCLIP_API_TOKEN, // verified non-empty
});
Defensive patterns

Strategy: validation

Validate before calling

function ensureHostApiToken(token: string | null | undefined): string {
  const trimmed = token?.trim() ?? "";
  if (trimmed.length === 0) {
    throw new Error("hostApiToken is required for sandbox bridge mode. Set PAPERCLIP_API_TOKEN or pass it explicitly.");
  }
  return trimmed;
}
// Call before ensureAdapterExecutionTargetPaperclipBridge
const hostApiToken = ensureHostApiToken(process.env.PAPERCLIP_API_TOKEN);

Type guard

function hasHostApiToken(input: { hostApiToken?: string | null }): boolean {
  return typeof input.hostApiToken === "string" && input.hostApiToken.trim().length > 0;
}

Prevention

When it happens

Trigger: Calling ensureAdapterExecutionTargetPaperclipBridge(input) where adapterExecutionTargetUsesPaperclipBridge(input.target) is true, input.target.kind === 'remote', and input.hostApiToken?.trim() yields an empty string.

Common situations: The Paperclip API token was not configured in the agent/company settings; the token environment variable (PAPERCLIP_API_TOKEN or similar) is unset in the host process; the token value was accidentally set to an empty string in configuration; the caller forgot to thread the token through to the bridge setup.

Related errors


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