{"record":{"id":"2c21a82813e96649","repo":"RocketChat/Rocket.Chat","slug":"fileupload-error","errorCode":null,"errorMessage":"FileUpload_Error","messagePattern":"FileUpload_Error","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/client/hooks/useEndpointUploadMutation.ts","lineNumber":30,"sourceCode":"\tconst sendData = useUpload(endpoint as PathFor<'POST'>);\n\tconst dispatchToastMessage = useToastMessageDispatch();\n\n\treturn useMutation({\n\t\tmutationFn: async (formData: FormData): Promise<TData> => {\n\t\t\tconst data = sendData(formData);\n\t\t\tconst promise = data instanceof Promise ? data : data.promise;\n\t\t\tconst result = await promise;\n\n\t\t\tif (!result.success) {\n\t\t\t\tif (result.status) {\n\t\t\t\t\tthrow new Error(result.status);\n\t\t\t\t}\n\n\t\t\t\tif (typeof result.error === 'string') {\n\t\t\t\t\tthrow new Error(result.error);\n\t\t\t\t}\n\n\t\t\t\tthrow new Error(t('FileUpload_Error'));\n\t\t\t}\n\t\t\treturn result as TData;\n\t\t},\n\t\tonError: (error) => {\n\t\t\tdispatchToastMessage({ type: 'error', message: error });\n\t\t},\n\t\t...options,\n\t});\n};\n","sourceCodeStart":12,"sourceCodeEnd":40,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/client/hooks/useEndpointUploadMutation.ts#L12-L40","documentation":"The fallback error in useEndpointUploadMutation: the upload failed (success === false) but neither result.status nor result.error is a usable string, so the hook throws the localized generic message t('FileUpload_Error'). This is the catch-all so the user always sees a translated toast rather than a blank or English-only default.","triggerScenarios":"result.success === false AND result.status is falsy AND (result.error is not a string or is undefined). The server returned an UploadResult with success:false but no structured reason — e.g. an empty 200 body, or a body like { success: false }.","commonSituations":"Server bug returning success:false with no reason; network proxy/gateway stripping the response body; an apps-engine interceptor that resolves { success: false } without populating fields; a half-failed chunked upload where the final assembly returns a bare failure.","solutions":["Reproduce with the browser DevTools Network tab open and inspect the raw response body — the lack of status/error is the real defect.","Check the server logs for the upload handler's exception; the client cannot tell you more because the server sent no reason.","Ensure any apps-engine upload interceptor populates both `status` and `error` on failure so users get an actionable message.","If using a reverse proxy, confirm it does not truncate the JSON body for non-2xx-mapped 200 responses.","As a last resort, retry the upload; transient infrastructure issues can produce empty failure bodies."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"function isBareFailedUploadResult(r: UploadResult): boolean {\n  return !r.success && !r.status && typeof (r as any).error !== 'string';\n}","tryCatchPattern":"try {\n  await upload.mutateAsync(formData);\n} catch (e) {\n  if ((e as Error).message === t('FileUpload_Error')) {\n    // generic fallback — inspect network response for the real cause\n    console.error('Upload failed with no server reason');\n  }\n}","preventionTips":["Inspect the raw network response when this generic message appears — the server sent no reason.","Ensure reverse proxies do not strip the upload response body.","Make apps-engine interceptors return a populated status/error on failure."],"tags":["file-upload","mutation","i18n","fallback","server-response"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}