paperclipai/paperclip · error
Teams inline image download unavailable
Error message
Teams inline image download unavailable
What it means
fetchTeamsInlineImage downloads a Teams message inline image via a per-attachment fetcher that was registered when the attachment was admitted. If no fetcher exists for the given attachment, or the AbortSignal is already aborted, it throws 'Teams inline image download unavailable'. The download capability is intentionally ephemeral: fetchers exist only for attachments seen during inbound admission.
Source
Thrown at server/src/services/chat-sdk-runtime.ts:2825
throw Object.assign(
new Error("Telegram private response runtime unavailable"),
{ code: "CHAT_PROVIDER_PRETRANSPORT_REJECTED" },
);
}
return sendTelegramCallbackNotice(
{ receipt, text, botToken: this.telegramEphemeralBotToken },
fetchImpl,
);
}
/** Only attachments reconstructed by this runtime can use the batch budget. */
async fetchTeamsInlineImage(
attachment: Attachment,
signal: AbortSignal,
): Promise<Buffer> {
const fetcher = this.teamsInlineImageFetchers.get(attachment);
if (!fetcher || signal.aborted)
throw new Error("Teams inline image download unavailable");
return await fetcher(signal);
}
/** Called only after current inbound admission; installation App authority only. */
async resolveGitHubAttachmentComment(
request: GitHubAttachmentCommentRequest,
signal: AbortSignal,
): Promise<unknown> {
if (!this.githubAttachmentAppAuthority)
throw new GitHubAttachmentUnavailableError(
"github_attachment_canonical_authority_unavailable",
);
if (!isGitHubAttachmentCommentRequest(request))
throw new GitHubAttachmentUnavailableError(
"github_attachment_source_mismatch",
);
try {
signal.throwIfAborted();View on GitHub (pinned to 01ad858492)
Solutions
- Download the inline image during/soon after inbound admission while the registered fetcher is still alive
- Pass the exact same Attachment object reference produced by admission (not a cloned/deserialized copy)
- Check signal.aborted before calling and create a fresh AbortController for a new attempt
- If the runtime was replaced, re-admit the message or obtain a new download handle
Example fix
// before
const buf = await runtime.fetchTeamsInlineImage(clonedAttachment, signal);
// after
if (!signal.aborted) {
const buf = await runtime.fetchTeamsInlineImage(originalAttachment, signal);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (signal.aborted || !runtime.hasTeamsInlineImageFetcher(attachment)) return null;
Try / catch
try { return await runtime.fetchTeamsInlineImage(attachment, signal); } catch { return placeholderBuffer; } Prevention
- Download inline images during or immediately after inbound admission
- Pass the original attachment reference, never a cloned/deserialized copy
- Check signal.aborted before each download and use a fresh AbortController per attempt
When it happens
Trigger: Fetching an attachment that was never registered in this.teamsInlineImageFetchers (e.g. attachment data reconstructed or deserialized after admission, so the WeakMap/get lookup misses), or calling with an already-aborted AbortSignal.
Common situations: Re-hydrating an attachment object from DB/JSON so it no longer matches the original key; delayed download long after the inbound message was processed; caller cancels the request before invoking the fetch; runtime replaced and fetcher map cleared.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Image exceeds attachment bound
- Skipped ${applied.skippedMissingAttachmentObjects} attachmen
- github_attachment_canonical_html_unavailable
- github_attachment_canonical_file_unsupported
- github_attachment_canonical_image_count_invalid
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/37bfd88025077bf2.
Report an issue: GitHub.