paperclipai/paperclip · error

Unsupported bridge body encoding.

Error message

Unsupported bridge body encoding.

What it means

decodeSandboxBridgeBody only accepts bodyEncoding values of undefined, 'utf8', or 'base64'. Any other declared encoding string causes this throw before any decoding is attempted. The check exists because the decoder would otherwise have to guess how the body bytes were encoded, and permissive fallbacks could silently corrupt binary payloads.

Solutions

  1. Change the producer to use bodyEncoding: 'base64' for binary data or omit bodyEncoding / use 'utf8' for text.
  2. Check the exact spelling of bodyEncoding — the accepted values are exactly 'utf8' and 'base64' (case-sensitive).
  3. Re-encode the body using Buffer.from(body, 'base64') on the producing side and declare bodyEncoding: 'base64'.
  4. Align encoder and decoder versions so both sides share the same sandbox-callback-bridge-body codec (see sandboxBridgeBodyCodecSource).

Example fix

// before
const envelope = { body: raw.toString("hex"), bodyEncoding: "hex" };
// after
const envelope = { body: raw.toString("base64"), bodyEncoding: "base64" };
Defensive patterns

Strategy: type-guard

Validate before calling

const ALLOWED_ENCODINGS = new Set([undefined, "utf8", "base64"]);
function hasSupportedEncoding(envelope) {
  return ALLOWED_ENCODINGS.has(envelope?.bodyEncoding);
}
if (!hasSupportedEncoding(envelope)) throw new Error(`Unsupported bodyEncoding: ${envelope.bodyEncoding}`);

Type guard

function hasKnownEncoding(en: unknown): en is { body: string; bodyEncoding?: "utf8" | "base64" } {
  const e = en as { bodyEncoding?: unknown };
  return typeof en === "object" && en !== null &&
    (e.bodyEncoding === undefined || e.bodyEncoding === "utf8" || e.bodyEncoding === "base64");
}

Try / catch

try {
  const bytes = decodeSandboxBridgeBody(envelope, maxBodyBytes);
} catch (err) {
  if (err instanceof Error && err.message === "Unsupported bridge body encoding.") {
    throw new Error(`bodyEncoding '${envelope?.bodyEncoding}' not supported; use utf8 or base64`);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling decodeSandboxBridgeBody with an envelope whose bodyEncoding is set to any string other than 'utf8' or 'base64' (e.g. 'hex', 'binary', 'utf-8' with a hyphen, or a typo like 'base36').

Common situations: A producer serializing with a different Buffer encoding name than the bridge contract supports; hand-written client code using 'utf-8' (invalid identifier here) instead of 'utf8'; version drift where a newer encoder emits an encoding the older shared decoder does not know.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/d35d2fe7f0494c86. Report an issue: GitHub.

Appendix: source

Thrown at packages/adapter-utils/src/sandbox-callback-bridge-body.ts:24

/** JSON can escape each input byte as six characters. Metadata is bounded too. */
export function sandboxBridgeEnvelopeLimit(maxBodyBytes: number): number {
  return 6 * maxBodyBytes + 64 * 1024;
}

export function encodeSandboxBridgeBody(body: string | Buffer, maxBodyBytes: number): SandboxCallbackBridgeBody {
  if (Buffer.byteLength(body) > maxBodyBytes) throw new Error("Bridge body exceeded the configured size limit.");
  return Buffer.isBuffer(body) ? { body: body.toString("base64"), bodyEncoding: "base64" } : { body };
}

/** Self-contained so the same decoder can be embedded in the remote gateway. */
export function decodeSandboxBridgeBody(envelope: SandboxCallbackBridgeBody, maxBodyBytes: number): Buffer {
  if (!envelope || typeof envelope.body !== "string") throw new Error("Invalid bridge body.");
  if (envelope.bodyEncoding === undefined || envelope.bodyEncoding === "utf8") {
    if (Buffer.byteLength(envelope.body, "utf8") > maxBodyBytes) throw new Error("Bridge body exceeded the configured size limit.");
    return Buffer.from(envelope.body, "utf8");
  }
  if (envelope.bodyEncoding !== "base64") throw new Error("Unsupported bridge body encoding.");
  const value = envelope.body;
  if (value.length > 4 * Math.ceil(maxBodyBytes / 3)) throw new Error("Bridge body exceeded the configured size limit.");
  // Buffer.from is permissive; reject malformed input before allocating bytes.
  if (value.length % 4 !== 0 || /[^A-Za-z0-9+/=]/.test(value) || !/^[A-Za-z0-9+/]*={0,2}$/.test(value)) {
    throw new Error("Invalid bridge base64 body.");
  }
  const bytes = Buffer.from(value, "base64");
  if (bytes.length > maxBodyBytes) throw new Error("Bridge body exceeded the configured size limit.");
  if (bytes.toString("base64") !== value) throw new Error("Invalid bridge base64 body.");
  return bytes;
}

export function sandboxBridgeBodyCodecSource(): string {
  return [sandboxBridgeEnvelopeLimit, encodeSandboxBridgeBody, decodeSandboxBridgeBody]
    .map(fn => `const ${fn.name} = ${fn.toString()};`).join("\n");
}

View on GitHub (pinned to 3f1d897a7c)