paperclipai/paperclip · error
Sandbox callback bridge response write wrote invalid result
Error message
Sandbox callback bridge response write wrote invalid result JSON: ${error instanceof Error ? error.message : String(error)} What it means
Thrown by the command-managed writeResponseFile after the remote shell script completed successfully (requireSuccessfulResult passed, exit code 0) but stdout could not be parsed as JSON containing a wrote field. The script is expected to print {"wrote":true} or {"wrote":false}; anything else indicates the remote shell emitted unexpected text (banner, set -x trace, warning) that broke JSON.parse or did not contain wrote.
Source
Thrown at packages/adapter-utils/src/sandbox-callback-bridge.ts:607
"if [ -f \"$response_path\" ]; then",
" printf '{\"wrote\":false}\\n'",
" exit 0",
"fi",
"cat > \"$temp_path\"",
"mv \"$temp_path\" \"$response_path\"",
"printf '{\"wrote\":true}\\n'",
].join("\n"),
timeoutMs,
shellCommand,
body,
);
requireSuccessfulResult(`write bridge response ${responsePath}`, result);
try {
return {
wrote: JSON.parse(result.stdout.trim())?.wrote === true,
};
} catch (error) {
throw new Error(
`Sandbox callback bridge response write wrote invalid result JSON: ${error instanceof Error ? error.message : String(error)}`,
);
}
},
rename: async (fromPath, toPath) => {
await runChecked(
`rename ${fromPath}`,
`mkdir -p ${shellQuote(path.posix.dirname(toPath))} && mv ${shellQuote(fromPath)} ${shellQuote(toPath)}`,
);
},
remove: async (remotePath) => {
await runChecked(`remove ${remotePath}`, `rm -rf ${shellQuote(remotePath)}`);
},
};
}
async function writeBridgeResponse(
client: SandboxCallbackBridgeQueueClient,View on GitHub (pinned to 67001ec6eb)
Solutions
- Suppress remote shell noise: ensure the bridge runs with a clean non-interactive shell (bash --noprofile --norc -c '...') and that no .bashrc echoes to stdout.
- Move any MOTD/banner output to stderr on the remote host (PAM, sshd config).
- Check the runner's shellCommand setting — prefer bash with --noprofile --norc to skip startup files that emit stdout.
- Capture the raw stdout in your error handler to see exactly what the remote printed; the message includes the parse error but not the raw stdout, so add a log of result.stdout before parsing when debugging.
Example fix
// before: remote ~/.bashrc echoes a greeting to stdout // echo "Welcome" # <-- delete or redirect to stderr // after: keep startup files silent on non-interactive shells // in ~/.bashrc if [ -z "$PS1" ]; then return; fi # skip rest for non-interactive
Defensive patterns
Strategy: validation
Validate before calling
async function preflightRemoteShellIsSilent(runner: CommandManagedRuntimeRunner, remoteCwd: string): Promise<void> {
const result = await runShell(runner, remoteCwd, 'printf \'{"wrote":true}\\n\'', 5000, "bash");
try {
if (JSON.parse(result.stdout.trim())?.wrote !== true) {
throw new Error(`Unexpected stdout: ${result.stdout}`);
}
} catch (error) {
throw new Error(`Remote shell pollutes stdout; disable MOTD/.bashrc echoes: ${String(error)}`);
}
} Try / catch
try {
await client.writeResponseFile(responsePath, body, { requestPath });
} catch (error) {
if (error instanceof Error && error.message.startsWith("Sandbox callback bridge response write wrote invalid result JSON")) {
throw new BridgeError("Remote shell wrote non-JSON to stdout. Suppress MOTD/.bashrc echoes or switch to bash --noprofile --norc.", { cause: error });
}
throw error;
} Prevention
- Use a clean non-interactive shell (bash --noprofile --norc -c '...') via the bridge's shellCommand option.
- Move MOTD/banner output to stderr on the remote host (sshd PrintMotd no, Banner none).
- Guard ~/.bashrc with `if [ -z \"$PS1\" ]; then return; fi` so non-interactive sessions skip echoing logic.
- When debugging, log result.stdout verbatim before parsing to see the offending line.
When it happens
Trigger: Remote SSH session prints a login banner before the script, the shell is run with -x tracing that pollutes stdout, a remote .bashrc echoes text on non-interactive shells, or a partial script timeout left stdout truncated. The JSON.parse call at sandbox-callback-bridge.ts:604 throws, which is wrapped into this error message including the underlying parse error.
Common situations: SSH banners from MOTD or PAM modules that echo to stdout instead of stderr; interactive shell configs (PS1, echo statements) sourced for non-interactive sessions; shells with set -v or set -x enabled globally; or PATH/locale warnings printed to stdout. The shell quote/redirect discipline in the script keeps stderr separate, but any stdout noise trips this guard.
Related errors
- ${input.label} sync wrote invalid result JSON: ${error insta
- Timed out acquiring sandbox callback bridge response lock.
- Bridge response body exceeded the configured size limit of $
- Failed to parse JSON at ${filePath}: ${err instanceof Error
- --payload must be a JSON object
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/cb687ca84bd95425.
Report an issue: GitHub.