paperclipai/paperclip · error · Error
sync wrote invalid result JSON
Error message
${input.label} sync wrote invalid result JSON: ${error instanceof Error ? error.message : String(error)} What it means
Protocol-parsing failure after a sandbox sync upload: the shell pipeline (with optional sha verify) exited successfully but its trailing '{"uploaded":true}' marker failed to parse as JSON, so the upload result cannot be trusted from the command output alone.
Solutions
- Inspect the JSON error and retry the ${input.label} sync.
- Check for truncated writes in the sync result channel.
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at packages/adapter-utils/src/sandbox-callback-bridge.ts:1527 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/4c2d58a14bded9da.
Report an issue: GitHub.
Appendix: source
Thrown at packages/adapter-utils/src/sandbox-callback-bridge.ts:1667
* `sha256sum` nor `shasum` — then the skip cannot be proven and we conservatively
* re-upload (and the post-upload verify is best-effort, as noted inline).
*/
export async function syncRemoteTextFileWithHashSkip(input: {
runner: CommandManagedRuntimeRunner;
remoteCwd: string;
remoteDir: string;
remotePath: string;
body: string;
// Human-readable noun phrase used in fail-loud messages, e.g.
// "Sandbox callback bridge entrypoint" / "Process session remote script".
label: string;
// Short action label for `requireSuccessfulResult`, e.g.
// "sync sandbox callback bridge entrypoint".
action: string;
lockDir: string;
timeoutMs?: number | null;
shellCommand?: "bash" | "sh" | null;
}): Promise<{ uploaded: boolean; sha256: string }> {
const timeoutMs = normalizeTimeoutMs(input.timeoutMs, DEFAULT_BRIDGE_RESPONSE_TIMEOUT_MS);
const shellCommand = preferredShellForSandbox(input.shellCommand);
const remotePartial = `${input.remotePath}.partial`;
const remoteUploadPath = `${input.remotePath}.paperclip-upload.b64`;
const base64Body = toBuffer(Buffer.from(input.body, "utf8")).toString("base64");
const sha256 = createHash("sha256").update(input.body, "utf8").digest("hex");
const syncResult = await runShell(
input.runner,
input.remoteCwd,
[
"set -eu",
`remote_dir=${shellQuote(input.remoteDir)}`,
`remote_path=${shellQuote(input.remotePath)}`,
`remote_partial=${shellQuote(remotePartial)}`,
`remote_upload=${shellQuote(remoteUploadPath)}`,
`lock_dir=${shellQuote(input.lockDir)}`,
`expected_sha=${shellQuote(sha256)}`,View on GitHub (pinned to 3f1d897a7c)