paperclipai/paperclip · error
CreateOS returned an invalid process frame.
Error message
CreateOS returned an invalid process frame.
What it means
A non-empty line from the CreateOS process stream failed JSON.parse or did not produce an object (via the `object()` helper). The plugin expects every frame to be a JSON object event (heartbeat/data/exit/error); anything else is treated as a protocol violation and fails closed rather than being reconnected past.
Solutions
- Log/capture the offending line and compare it against the expected event schema (type: heartbeat|data|exit|error).
- Check for proxies or gateways between the plugin and CreateOS that could inject non-JSON bodies into the stream.
- Verify CreateOS service version compatibility; protocol changes can break frame parsing.
- Retry the command; if persistent, inspect the sandbox's process endpoint directly with curl to see the raw frames.
Example fix
// before
const ev = JSON.parse(line); // throws raw SyntaxError on bad frames
// after (plugin behavior)
try { const ev = object(JSON.parse(line)); } catch { /* invalid process frame */ } Defensive patterns
Strategy: try-catch
Try / catch
try { await execute(client, params, signal); }
catch (e) {
if (e instanceof Error && e.message === "CreateOS returned an invalid process frame.") {
log.error("Non-JSON frame from CreateOS; check proxies and service version");
// retry once, then fail with diagnostics
} else throw e;
} Prevention
- Bypass or audit proxies between the plugin and CreateOS that could inject HTML error pages.
- Keep the CreateOS service version aligned with the plugin protocol.
- Alert on this error: repeated occurrences mean server-side corruption, not transient faults.
- Capture raw stream frames during incidents for upstream bug reports.
When it happens
Trigger: The /processes/:id/connect stream emits a line that is invalid JSON (truncated frame, HTML error page, plain-text message), or valid JSON that is not an object (array, string, number).
Common situations: A proxy/load balancer injects an HTML 502 page into the stream; the sandbox command echoes non-JSON directly into the event channel due to a server-side framing bug; a CreateOS protocol version change renames or restructures event payloads.
Understand the failure class
Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.
Related errors
- CreateOS process exit status is missing.
- CreateOS process output has a sequence gap.
- CreateOS process output is invalid.
- CreateOS process sequence is invalid.
- Photon attachment header is missing
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/679db4c073b9a744.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugins/sandbox-providers/createos/src/execute.ts:62
pending = pending.slice(newline + 1);
if (line.length > MAX_LINE_BYTES) throw new Error("CreateOS process frame is too large.");
if (line.trim()) yield parseEvent(line);
}
if (pending.length > MAX_LINE_BYTES) throw new Error("CreateOS process frame is too large.");
if (done) {
if (pending.trim()) yield parseEvent(pending);
return;
}
}
} finally {
await reader.cancel().catch(() => undefined);
reader.releaseLock();
}
}
function parseEvent(line: string): Record<string, unknown> {
try { return object(JSON.parse(line)); }
catch { throw new Error("CreateOS returned an invalid process frame."); }
}
class Output {
stdout = "";
stderr = "";
truncated = false;
private decoders = { stdout: new StringDecoder("utf8"), stderr: new StringDecoder("utf8") };
constructor(private log: (stream: "stdout" | "stderr", text: string) => void) {}
private append(stream: "stdout" | "stderr", text: string) {
if (!text) return;
this.log(stream, text);
const combined = this[stream] + text;
if (combined.length > MAX_CAPTURE_CHARS) this.truncated = true;
this[stream] = combined.slice(-MAX_CAPTURE_CHARS);
}
write(stream: "stdout" | "stderr", bytes: Buffer) {View on GitHub (pinned to 3f1d897a7c)