paperclipai/paperclip · error
CreateOS process output connection failed.
Error message
CreateOS process output connection failed.
What it means
The plugin failed to (re)establish the /processes/:id/connect connection more than 3 times (only 5xx/429 errors are retried, with 250 ms backoff). This means the output stream endpoint is persistently unreachable or erroring, so process output cannot be read.
Solutions
- Retry the whole execute call after verifying the CreateOS service is healthy (/health or equivalent).
- Check rate limiting: 429 responses exhaust the 3-retry budget quickly; reduce concurrency or add backoff at the caller level.
- Verify the configured CreateOS base URL, DNS, and network reachability to the sandbox host.
- Inspect server logs for 5xx on the /connect route during the failure window.
- Note the process tree is terminated by cleanup on this error; a rerun is safe.
Example fix
// before
await client.request(`${base}/${processId}/connect?after=${cursor}`); // fails, no budget left
// after (caller-side)
for (let i = 0; i < 3; i++) { try { return await execute(client, params, signal); } catch (e) { if (!/connection failed/.test(e.message)) throw e; await sleep(2 ** i * 250); } } Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight reachability check
const probe = await fetch(`${baseUrl}/sandboxes/${leaseId}/processes`, { method: "HEAD" }).catch(() => null);
if (!probe) throw new Error("CreateOS host unreachable before execute"); Try / catch
try { await execute(client, params, signal); }
catch (e) {
if (e instanceof Error && e.message === "CreateOS process output connection failed.") {
await sleep(1000); // service-level backoff, then re-run execute (cleanup already killed the tree)
} else throw e;
} Prevention
- Check CreateOS service health before batch runs.
- Respect 429 rate limits; throttle concurrent executes.
- Verify base URL, DNS, and TLS configuration.
- Monitor 5xx rates on the /connect route.
When it happens
Trigger: Four consecutive connect attempts fail with 5xx or 429 (or a network error classified as retryable), e.g. the CreateOS host is down, DNS fails, TLS fails, or the server is rate-limiting /connect beyond the retry budget.
Common situations: CreateOS service restart or outage during a command; aggressive rate limiting after many concurrent executes; firewall/DNS misconfiguration in the sandbox base URL; load balancer returning 503s for the connect route.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- GitHub Actions read failed
- OpenCode API request failed
- unavailable
- Anthropic Managed Agents request failed with HTTP
- / : oauth requires ownershipModes
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/8666f3fa6e9d2d13.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugins/sandbox-providers/createos/src/execute.ts:145
processId = identifier(created.process_id);
// No interactive stdin for ordinary commands; any supplied input comes
// from the staged file, avoiding a write-vs-fast-exit race.
try { await client.json(`${base}/${processId}/stdin/close`, "POST", undefined, signal); }
catch (error) {
if (!(error instanceof CreateosApiError && error.status === 409)) throw error;
}
let reconnects = 0;
for (;;) {
signal.throwIfAborted();
let response: Response;
try {
response = await client.request(`${base}/${processId}/connect?after=${cursor}`, { signal });
} catch (error) {
if (error instanceof CreateosApiError && error.status === 410) {
throw new Error("CreateOS process output was evicted before it could be read.");
}
if (signal.aborted || (error instanceof CreateosApiError && error.status < 500 && error.status !== 429)) throw error;
if (++reconnects > 3) throw new Error("CreateOS process output connection failed.");
await delay(250, undefined, { signal });
continue;
}
try {
for await (const event of events(response)) {
if (event.type === "heartbeat") continue;
if (event.type === "data") {
const seq = event.seq;
if (typeof seq !== "number" || !Number.isSafeInteger(seq) || seq < 1) throw new Error("CreateOS process sequence is invalid.");
if (seq <= cursor) continue;
if (seq !== cursor + 1) throw new Error("CreateOS process output has a sequence gap.");
if ((event.stream !== "stdout" && event.stream !== "stderr") ||
typeof event.data_base64 !== "string" ||
!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(event.data_base64)) {
throw new Error("CreateOS process output is invalid.");
}
output.write(event.stream, Buffer.from(event.data_base64, "base64"));
cursor = seq;View on GitHub (pinned to 3f1d897a7c)