paperclipai/paperclip · error · GitHubAttachmentUnavailableError
github_attachment_download_failed
github_attachment_download_failed
Error message
github_attachment_download_failed
What it means
The outer catch of prepareGitHubPublicAttachment (chat-github-attachments.ts:850-855) rethrows GitHubAttachmentUnavailableError as-is, but wraps any other thrown value — network failures, DNS errors, timeouts, SSRF-guard rejections from guardedRemoteHttpFetch, AbortSignal timeouts, URL parse errors — into a generic GitHubAttachmentUnavailableError with code "github_attachment_download_failed". It is the umbrella error meaning the download could not be completed for a reason not covered by a more specific code.
Source
Thrown at server/src/services/chat-github-attachments.ts:852
type: mimeType.startsWith("image/")
? "image"
: mimeType.startsWith("audio/")
? "audio"
: mimeType.startsWith("video/")
? "video"
: "file",
name,
mimeType,
size,
fetchData: async () => body,
};
}
throw new GitHubAttachmentUnavailableError(
"github_attachment_unsafe_redirect",
);
} catch (error) {
if (error instanceof GitHubAttachmentUnavailableError) throw error;
throw new GitHubAttachmentUnavailableError(
"github_attachment_download_failed",
);
}
}
View on GitHub (pinned to 01ad858492)
Solutions
- Check server egress: curl the attachment URL from the server host to test DNS/firewall reachability
- Verify DOWNLOAD_TIMEOUT_MS is adequate for large attachments on slow links
- Log/inspect the underlying cause — the original error is swallowed, so reproduce with the same URL outside the wrapper
- Confirm the attachment locator URL is a valid absolute http(s) URL
Example fix
// before: opaque failure with no visibility
} catch (error) {
throw new GitHubAttachmentUnavailableError("github_attachment_download_failed");
}
// after: preserve the cause for diagnosis
} catch (error) {
if (error instanceof GitHubAttachmentUnavailableError) throw error;
logger.warn("github attachment download failed", { cause: String(error) });
throw new GitHubAttachmentUnavailableError("github_attachment_download_failed");
} Defensive patterns
Strategy: retry
Validate before calling
const u = new URL(attachment.url); if (u.protocol !== "https:") throw new Error("attachment locator must be https"); // check egress once at boot: await fetch("https://github.com/robots.txt") Type guard
function hasValidLocator(a) { if (!a?.url) return false; try { const u = new URL(a.url); return u.protocol === "https:"; } catch { return false; } } Try / catch
try { return await prepareGitHubPublicAttachment(attachment, signal, resolveComment); } catch (e) { if (e?.code === "github_attachment_download_failed") { if (isRetryable(signal)) return retry(prepareGitHubPublicAttachment, attachment); return downloadFailedCard(attachment); } throw e; } Prevention
- Allowlist egress to github.com and objects.githubusercontent.com in firewall/proxy config
- Size DOWNLOAD_TIMEOUT_MS for the largest expected attachment
- Preserve/log the underlying cause when wrapping errors
- Validate stored attachment URLs are absolute https URLs
When it happens
Trigger: guardedRemoteHttpFetch rejects (connect timeout 5000ms, private-network target blocked, DNS failure); AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) fires; new URL(locator.url) throws on a malformed stored URL; any non-GitHubAttachmentUnavailableError exception inside the try block.
Common situations: No outbound internet access / DNS misconfiguration on the server host; corporate firewall blocking objects.githubusercontent.com; long downloads exceeding DOWNLOAD_TIMEOUT_MS; attachment handles whose stored locator URL got corrupted; IPv6 vs IPv4 egress issues.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- github_attachment_canonical_html_unavailable
- github_attachment_canonical_file_unsupported
- github_attachment_canonical_image_count_invalid
- github_attachment_canonical_target_denied
- github_attachment_canonical_mapping_ambiguous
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/17632056f7a03775.
Report an issue: GitHub.