paperclipai/paperclip · warning
paperclip_runner_chat_attachment_read_aborted
paperclip_runner_chat_attachment_read_aborted
Error message
paperclip_runner_chat_attachment_read_aborted
What it means
Storage fetches race against an abort signal combining scope closure with a storage timeout (default 5s). If the signal fires — scope closed or storage did not deliver the object in time — the object stream is destroyed and this error is thrown from #bytes via the aborted promise.
Solutions
- Increase storageTimeoutMs when reading large attachments or over slow links.
- Check storage backend health/latency (S3 region, network path).
- Retry the read once; transient storage slowness often resolves.
- If scope closure causes it, stop issuing reads once the run is ending.
Example fix
// before
new NativeChatAttachmentReadScope({ ..., storageTimeoutMs: undefined }); // 5s default
// after
new NativeChatAttachmentReadScope({ ..., storageTimeoutMs: 30_000 }); Defensive patterns
Strategy: retry
Type guard
function isAbortedError(e: unknown): boolean {
return e instanceof Error && e.message === "paperclip_runner_chat_attachment_read_aborted";
} Try / catch
try {
return await scope.read(input);
} catch (e) {
if (isAbortedError(e)) {
await new Promise(r => setTimeout(r, 200));
return scope.read(input); // retry unless the scope was closed
}
throw e;
} Prevention
- Raise storageTimeoutMs for large attachments or slow storage.
- Monitor storage backend latency and error rates.
- Stop issuing reads once close() has been requested.
- Prefer local/fast storage for the run workspace path.
When it happens
Trigger: Storage backend (S3/local) taking longer than storageTimeoutMs (default 5000ms) to return the object; scope.close() called while a read was streaming; AbortSignal.timeout firing on a slow or hung storage provider.
Common situations: Slow or degraded object storage; large attachments on high-latency links; network partitions; runs being torn down concurrently with reads.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- CreateOS process stream ended without an exit status.
- GitHub Actions read failed
- github_attachment_download_failed
- github_webhook_recovery_transport
- network
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/5c172af0a0022543.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/native-runtime/chat-attachment-read.ts:223
AbortSignal.timeout(this.options.storageTimeoutMs ?? 5_000),
]);
let object: Awaited<ReturnType<StorageService["getObject"]>> | undefined;
const aborted = new Promise<never>((_, reject) => {
signal.addEventListener(
"abort",
() => {
object?.stream.destroy();
reject(new Error("paperclip_runner_chat_attachment_read_aborted"));
},
{ once: true },
);
});
const acquiring = storage
.getObject(this.options.binding.companyId, source.objectKey)
.then((value) => {
if (signal.aborted) {
value.stream.destroy();
throw new Error("paperclip_runner_chat_attachment_read_aborted");
}
object = value;
return value;
});
const read = (async () => {
const value = await acquiring;
const chunks: Buffer[] = [];
let length = 0;
try {
for await (const chunk of value.stream) {
const bytes = Buffer.from(chunk);
length += bytes.length;
if (length > source.byteSize || length > MAX_ATTACHMENT_BYTES)
throw new Error(
"paperclip_runner_chat_attachment_read_size_mismatch",
);
chunks.push(bytes);
}View on GitHub (pinned to 3f1d897a7c)