paperclipai/paperclip · critical
Sandbox callback bridge did not report a listening port.
Error message
Sandbox callback bridge did not report a listening port.
What it means
Thrown when the parsed readiness JSON exists but its `port` field is missing, zero, or non-finite. The bridge server is expected to bind a TCP port and report it; a port of 0/NaN means the server either failed to listen (e.g. port 0 ephemeral was requested but the write of the real port never happened) or wrote a non-numeric port. This is a fail-closed guard so the orchestrator never returns a baseUrl pointing at port 0.
Source
Thrown at packages/adapter-utils/src/sandbox-callback-bridge.ts:1113
shellCommand,
);
requireSuccessfulResult("wait for sandbox callback bridge readiness", readyResult);
let readyData: { host?: string; port?: number; baseUrl?: string; pid?: number };
try {
readyData = JSON.parse(readyResult.stdout.trim()) as { host?: string; port?: number; baseUrl?: string; pid?: number };
} catch (error) {
throw new Error(
`Sandbox callback bridge wrote invalid readiness JSON: ${error instanceof Error ? error.message : String(error)}`,
);
}
const host = typeof readyData.host === "string" && readyData.host.trim().length > 0
? readyData.host.trim()
: "127.0.0.1";
const port = typeof readyData.port === "number" && Number.isFinite(readyData.port) ? readyData.port : 0;
if (!port) {
throw new Error("Sandbox callback bridge did not report a listening port.");
}
const baseUrl =
typeof readyData.baseUrl === "string" && readyData.baseUrl.trim().length > 0
? readyData.baseUrl.trim()
: `http://${host}:${port}`;
return {
baseUrl,
host,
port,
pid: typeof readyData.pid === "number" && Number.isFinite(readyData.pid) ? readyData.pid : 0,
directories,
stop: async () => {
const stopResult = await input.runner.execute({
command: shellCommand,
args: shellCommandArgs(
[
`if [ -s ${shellQuote(directories.pidFile)} ]; then`,View on GitHub (pinned to 67001ec6eb)
Solutions
- Read the generated bridge server source (getSandboxCallbackBridgeServerSource) and confirm it writes the real bound port into ready.json after `server.listen`.
- Check directories.logFile on the remote host for a bridge runtime error after the listen call.
- Confirm PAPERCLIP_BRIDGE_PORT was not forced to a non-listenable value and that the bridge host can bind.
- Log readyData verbatim before the port check to see which field is malformed.
Defensive patterns
Strategy: validation
Validate before calling
const readyData = JSON.parse(raw) as { port?: unknown };
if (typeof readyData.port !== 'number' || !Number.isFinite(readyData.port) || readyData.port <= 0) {
throw new Error(`Bridge did not bind a port; readyData=${JSON.stringify(readyData)}`);
} Type guard
function hasValidPort(v: unknown): v is { port: number } {
return typeof (v as { port?: unknown })?.port === 'number'
&& Number.isFinite((v as { port: number }).port)
&& (v as { port: number }).port > 0;
} Prevention
- Pin the generated bridge server source so the listen callback always writes the real bound port.
- Integration-test the bridge against an ephemeral port and assert a positive port is reported.
- Watch for regressions in getSandboxCallbackBridgeServerSource that drop the port field.
When it happens
Trigger: startSandboxCallbackBridge parsed readyData successfully but readyData.port is undefined, 0, Infinity, -1, or a string coerced away. Occurs when the remote bridge binds but its ready.json write omits `port`, or writes port 0 because process.env.PAPERCLIP_BRIDGE_PORT defaulted and the actual bound port was not written back.
Common situations: Bridge server code path changed and stopped emitting port; the `server.listen(0)` callback that writes ready.json was replaced; a port string vs number type regression in the bridge source generator; bridge process started but crashed after listening, before writing port.
Related errors
- Sandbox callback bridge wrote invalid readiness JSON: ${erro
- Failed to start sandbox ACP process session bridge: ${startR
- Sandbox bridge mode requires a host-side Paperclip API token
- networkAllowlist[${index}] must not be empty.
- networkAllowlist[${index}] must be a hostname, hostname:port
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/f6863f2695d08c17.
Report an issue: GitHub.