paperclipai/paperclip · error · Error
Sandbox bridge mode requires a host-side Paperclip API…
Error message
Sandbox bridge mode requires a host-side Paperclip API token.
What it means
Authentication precondition for sandbox bridge mode: the bridge relays sandbox callbacks to the host Paperclip API, which requires a host-side API token, and none was provided on the target configuration.
Solutions
- Provide a host-side Paperclip API token for sandbox bridge mode.
- Use a non-bridge execution mode if no token is available.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/adapter-utils/src/execution-target.ts:2215 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-08-18).
Data as JSON: /api/errors/bc9c33aebac58d56.
Report an issue: GitHub.
Appendix: source
Thrown at packages/adapter-utils/src/execution-target.ts:2511
// only shorten this wait and suppress the warning below; it never
// gates, shortens, or replaces the unconditional removal further down.
// What actually makes the wrapper's own termination deterministic is
// the wrapper-side session-identity latch, not this event.
let acknowledgedInTime = false;
readShutdownAckUntil(Date.now() + DEFAULT_PROCESS_SESSION_SHUTDOWN_WAIT_MS);
await Promise.race([
shutdownAcknowledged.then(() => {
acknowledgedInTime = true;
}),
new Promise<void>((resolve) => {
const budgetTimer = setTimeout(resolve, DEFAULT_PROCESS_SESSION_SHUTDOWN_WAIT_MS);
budgetTimer.unref?.();
}),
]);
stopReadingForShutdownAck = true;
if (!acknowledgedInTime) {
await onLog(
"stderr",
`[paperclip] ACP process session wrapper did not acknowledge shutdown within ${DEFAULT_PROCESS_SESSION_SHUTDOWN_WAIT_MS}ms; removing the session directory anyway.\n`,
).catch(() => undefined);
}
// Unconditional: this removal runs whether or not the wrapper
// acknowledged, and whether or not any event (real or forged) arrived
// under `sessionDir`. `stop()` runs during run teardown and must stay
// non-fatal, so every step above is best-effort and this step never
// throws.
await client.remove(sessionDir).catch(() => undefined);
await fs.rm(proxyDir, { recursive: true, force: true }).catch(() => undefined);
},
};
}
function getProcessSessionProxySource(input: { port: number; token: string }): string {
return `#!/usr/bin/env node
import net from "node:net";
View on GitHub (pinned to 3f1d897a7c)