paperclipai/paperclip · error · Error
Unsupported storage response body.
Error message
Unsupported storage response body.
What it means
Thrown by s3BodyToBuffer when the storage response body is a non-empty object but exposes none of the supported consumption interfaces: it is not a Buffer, not a Node Readable stream, and has neither transformToWebStream nor arrayBuffer methods. The helper cannot materialize bytes from it.
Source
Thrown at cli/src/commands/worktree.ts:347
transformToWebStream?: () => ReadableStream<Uint8Array>;
arrayBuffer?: () => Promise<ArrayBuffer>;
};
if (typeof candidate.transformToWebStream === "function") {
const webStream = candidate.transformToWebStream();
const reader = webStream.getReader();
const chunks: Uint8Array[] = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
if (value) chunks.push(value);
}
return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)));
}
if (typeof candidate.arrayBuffer === "function") {
return Buffer.from(await candidate.arrayBuffer());
}
throw new Error("Unsupported storage response body.");
}
function normalizeS3Prefix(prefix: string | undefined): string {
if (!prefix) return "";
return prefix.trim().replace(/^\/+/, "").replace(/\/+$/, "");
}
function buildS3ObjectKey(prefix: string, objectKey: string): string {
return prefix ? `${prefix}/${objectKey}` : objectKey;
}
const dynamicImport = new Function("specifier", "return import(specifier);") as (specifier: string) => Promise<any>;
function createConfiguredStorageFromPaperclipConfig(config: PaperclipConfig): ConfiguredStorage {
if (config.storage.provider === "local_disk") {
const baseDir = expandHomePrefix(config.storage.localDisk.baseDir);
return {
async getObject(companyId: string, objectKey: string) {View on GitHub (pinned to 67001ec6eb)
Solutions
- Pin or upgrade @aws-sdk/client-s3 to a version whose Body is a Node Readable or has transformToWebStream/arrayBuffer.
- In tests, return a Readable.from(Buffer) or an object exposing arrayBuffer()/transformToWebStream() rather than a plain object.
- If using a custom S3-compatible client adapter, normalize its Body to one of the supported shapes before returning.
- Check for duplicate/incompatible @aws-sdk versions in node_modules (pnpm why @aws-sdk/client-s3).
Example fix
// before (test mock)
getObject: async () => ({ Body: { data: 'hi' } })
// after
getObject: async () => ({ Body: Readable.from(Buffer.from('hi')) }) Defensive patterns
Strategy: type-guard
Validate before calling
function isConsumableBody(body: unknown): boolean {
return !!body && (
Buffer.isBuffer(body) ||
body instanceof Readable ||
typeof (body as any)?.transformToWebStream === 'function' ||
typeof (body as any)?.arrayBuffer === 'function'
);
} Type guard
function isSupportedBody(body: unknown): body is Buffer | Readable | { transformToWebStream(): ReadableStream<Uint8Array> } | { arrayBuffer(): Promise<ArrayBuffer> } {
return isConsumableBody(body);
} Try / catch
try {
return await s3BodyToBuffer(resp.Body);
} catch (e) {
if (e instanceof Error && e.message === 'Unsupported storage response body.') {
throw new Error('S3 SDK version mismatch: update @aws-sdk/client-s3');
}
throw e;
} Prevention
- Pin @aws-sdk/client-s3 to a tested major version.
- In tests, return Readable.from(Buffer) or an object with arrayBuffer().
- Check for duplicate @aws-sdk copies with pnpm why.
When it happens
Trigger: Using an @aws-sdk/client-s3 version whose response Body type differs (e.g. a newer SDK returning a different streaming primitive); mocking S3 responses with a plain object or string body; an S3-compatible vendor SDK that wraps responses in an unsupported shape; runtime where Readable cross-realm instanceof checks fail.
Common situations: Major @aws-sdk/client-s3 version upgrade changing the Body payload contract; polyfilled streams where instanceof Readable is unreliable across module realms; returning a string or TypedArray directly from a test double.
Related errors
- Object not found.
- Import transfer declaration returned no data.
- Request failed with status ${response.status}
- Paperclip server entrypoint did not export startServer(): ${
- Invalid object key for company ${companyId}.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/771b27994f73428e.
Report an issue: GitHub.