{"record":{"id":"e4ba95762d7f1386","repo":"jitsi/jitsi-meet","slug":"could-not-download-file","errorCode":null,"errorMessage":"Could not download file:","messagePattern":"Could not download file:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"react/features/file-sharing/middleware.web.ts","lineNumber":248,"sourceCode":"                'Authorization': `Bearer ${token}`\n            }\n        }))\n        .then((response: any) => response.json())\n        .then((data: { fileName: string; presignedUrl: string; }) => {\n            const { presignedUrl, fileName } = data;\n\n            if (!presignedUrl) {\n                throw new Error('No presigned URL found in the response.');\n            }\n\n            store.dispatch(showNotification({\n                titleKey: 'fileSharing.downloadStarted'\n            }, NOTIFICATION_TIMEOUT_TYPE.SHORT));\n\n            return downloadFile(presignedUrl, fileName);\n        })\n        .catch((error: any) => {\n            logger.warn('Could not download file:', error);\n\n            store.dispatch(showErrorNotification({\n                titleKey: 'fileSharing.downloadFailedTitle',\n                descriptionKey: 'fileSharing.downloadFailedDescription',\n                appearance: NOTIFICATION_TYPE.ERROR\n            }, NOTIFICATION_TIMEOUT_TYPE.STICKY));\n        });\n\n        return next(action);\n    }\n\n    case _FILE_REMOVED: {\n        const result = next(action);\n        const state = store.getState();\n        const { messages } = state['features/chat'];\n\n        // Find the message corresponding to this file and mark it as deleted.\n        const fileMessage = messages.find(msg => msg.messageId === action.fileId);","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/jitsi/jitsi-meet/blob/98de6219cc7ddbe07ace9fde045aff90a242ba01/react/features/file-sharing/middleware.web.ts#L230-L266","documentation":"A logger.warn in the file-sharing web middleware: downloading a shared file via its presigned URL failed. The promise chain from the download attempt (fetch/save of the presigned URL) rejects, the catch logs 'Could not download file:' with the underlying error, and a sticky 'download failed' notification is dispatched.","triggerScenarios":"The presigned URL is expired or revoked (S3/URL TTL passed), the storage backend is unreachable, CORS blocks the GET from the browser, the file was deleted server-side, or a network failure/abort occurs during fetch.","commonSituations":"User clicks a share link long after upload and the presigned URL expired; file-sharing storage (S3/other) misconfigured or bucket deleted; missing CORS headers on the object store; reverse proxy timeouts on large files; flaky client network.","solutions":["Check the logged error object: 403 signature/expiry means expired presigned URL — re-request a fresh URL from the file-sharing backend and retry; network/CORS errors point to storage config","Verify CORS configuration on the file storage allows GET from the deployment origin","Confirm the file still exists server-side and the sharing service issues URLs with adequate TTL","Add a retry with a freshly minted presigned URL before surfacing the sticky failure notification"],"exampleFix":"// before\nreturn downloadFile(presignedUrl, fileName);\n\n// after\nreturn downloadFile(presignedUrl, fileName).catch(async error => {\n    logger.warn('Could not download file:', error);\n    if (error?.status === 403 || error?.name === 'AbortError') {\n        const fresh = await fetchNewPresignedUrl(fileUrl); // backend re-sign\n        return downloadFile(fresh, fileName);\n    }\n    throw error;\n});","handlingStrategy":"retry","validationCode":"// Check URL freshness before downloading (presigned URLs carry Expires param)\nconst isFresh = (url: string): boolean => {\n    const expires = new URL(url).searchParams.get('Expires');\n    return !expires || Number(expires) * 1000 > Date.now() + 30_000;\n};\nif (!isFresh(presignedUrl)) {\n    presignedUrl = await refreshPresignedUrl(fileName);\n}","typeGuard":"const isDownloadError = (e: unknown): e is { status: number; message: string } =>\n    typeof e === 'object' && e !== null && 'status' in e;","tryCatchPattern":".catch((error: unknown) => {\n    logger.warn('Could not download file:', error);\n    if (isDownloadError(error) && (error.status === 403 || error.status === 410)) {\n        return refreshAndRetryDownload(fileName); // get fresh presigned URL\n    }\n    store.dispatch(showErrorNotification({\n        titleKey: 'fileSharing.downloadFailedTitle',\n        descriptionKey: 'fileSharing.downloadFailedDescription'\n    }, NOTIFICATION_TIMEOUT_TYPE.STICKY));\n})","preventionTips":["Issue presigned URLs with TTLs that comfortably exceed expected share lifetime","Refresh/re-sign URLs lazily at click time rather than embedding long-lived ones in messages","Configure CORS on the object store for GET from the app origin","Retry transient network failures once with a fresh URL before showing the sticky error"],"tags":["file-sharing","presigned-url","download","s3","cors","network"],"backgroundTag":"presigned-url-download-failed","analyzedSha":"98de6219cc7ddbe07ace9fde045aff90a242ba01","analyzedAt":"2026-08-28T15:15:59.482Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}