RocketChat/Rocket.Chat · error · Error
Failed to fetch encrypted PDF: ${response.status}
Error message
Failed to fetch encrypted PDF: ${response.status} What it means
Thrown by useOpenEncryptedPdf when the fetch() for an encrypted PDF attachment returns a non-ok HTTP status (response.ok === false). The message embeds response.status (e.g. 401, 403, 404, 500) so the developer can see why the media fetch failed. The fetch targets getURL(link) on the media host; non-2xx means the resource could not be retrieved.
Source
Thrown at apps/meteor/client/components/message/content/attachments/file/hooks/useOpenEncryptedPdf.ts:59
if (blobUrlRef.current) {
URL.revokeObjectURL(blobUrlRef.current);
blobUrlRef.current = undefined;
}
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
const abortController = new AbortController();
abortControllerRef.current = abortController;
try {
const response = await fetch(getURL(link), {
signal: abortController.signal,
});
if (!response.ok) {
throw new Error(`Failed to fetch encrypted PDF: ${response.status}`);
}
const blob = await response.blob();
if (abortController.signal.aborted || abortControllerRef.current !== abortController) {
return;
}
const blobUrl = URL.createObjectURL(blob);
blobUrlRef.current = blobUrl;
openDocumentViewer(blobUrl, format, title ?? '');
} catch (error: any) {
if (error.name !== 'AbortError') {
console.error('Error opening preview of encrypted PDF', error);
throw error;
}
}
};
return openEncryptedPdf;
};View on GitHub (pinned to f9d3ec372b)
Solutions
- Read response.status from the message: 401/403 → auth/permission, 404 → missing attachment, 5xx → server/storage.
- For 401/403, verify the session token is sent with the media request and the user has access to the room/attachment.
- For 404, confirm the attachment still exists (it may have been purged).
- Ensure credentials are included in the fetch if the media host differs from the app host (sameSite/CORS).
- If the PDF exceeds pdfPreviewSizeLimitInBytes the hook downloads instead of previewing — confirm size handling is intended.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check access before fetching the encrypted PDF
if (!hasAtLeastOnePermission('preview-file', roomId)) {
throw new Error('Permission denied');
} Type guard
function isOkResponse(r: Response): boolean {
return r.ok;
} Try / catch
try {
await openEncryptedPdf(link, title, size, format, openViewer);
} catch (e) {
const status = (e as Error).message.match(/(\d+)$/)?.[1];
if (status === '401' || status === '403') { redirectToLogin(); }
else if (status === '404') { showAttachmentMissing(); }
} Prevention
- Ensure the auth token/cookie is sent with the media fetch (credentials config).
- Verify the user has preview/read permission for the attachment's room.
- Parse the trailing status code from the message to branch handling.
When it happens
Trigger: The encrypted PDF blob endpoint returned 401 (token expired/not supplied), 403 (no permission for the room/attachment), 404 (attachment deleted or wrong link), or 5xx (media store/S3 failure). The check `if (!response.ok)` fires before reading the blob and throws the templated message.
Common situations: E2E encryption key not available so the server rejects the fetch; the user lacks 'preview-file' permission; the attachment was deleted; the S3/gridfs backing store is unreachable; the auth cookie/token was not sent with the fetch (CORS or credentials config).
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/741a09bced30aa9a.
Report an issue: GitHub.