RocketChat/Rocket.Chat · error

FileUpload_Error

Error message

FileUpload_Error

What it means

Thrown by the upload mutation wrapper in useEndpointUploadMutation when the awaited upload result has success === false but carries neither a result.status nor a string result.error, so no specific message can be extracted. The message is the i18n key 'FileUpload_Error', which the hook's onError renders as an error toast via dispatchToastMessage. It is the generic fallback for uploads that fail without a structured JSON error payload.

Solutions

  1. Inspect the actual upload response in the browser Network tab and fix the underlying HTTP failure (413 size limit, 401 auth, 502 proxy) first.
  2. Validate the file client-side against FileUpload_MaxFileSize and allowed media types before calling mutate.
  3. If you control the endpoint, return a JSON body with a status field so result.status is propagated instead of this generic message.
  4. Wrap mutateAsync in try/catch (or rely on onError) to show a specific message or offer a retry.

Example fix

// before
const { mutateAsync } = useEndpointUploadMutation('POST', '/v1/rooms.upload/{rid}', { promise: true });
await mutateAsync(file); // generic FileUpload_Error toast on failure

// after
const maxFileSize = settings.get('FileUpload_MaxFileSize') ?? 0;
if (maxFileSize && file.size > maxFileSize) {
  dispatchToastMessage({ type: 'error', message: t('File_exceeds_allowed_size_of_s', { size: maxFileSize }) });
} else {
  await mutateAsync(file);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const maxBytes = settings.get('FileUpload_MaxFileSize') ?? 0;
if (maxBytes && file.size > maxBytes) {
  dispatchToastMessage({ type: 'error', message: t('File_exceeds_allowed_size_of_s', { size: maxBytes }) });
  return;
}
// also verify allowed media types before mutating
await mutateAsync(file);

Try / catch

try {
  const result = await mutateAsync(file);
} catch (e) {
  // the hook's onError already toasts; branch here for retry/telemetry
  if (e instanceof Error) {
    reportUploadFailure(file.name, e.message);
  }
}

Prevention

When it happens

Trigger: Calling mutate/mutateAsync on a mutation built with useEndpointUploadMutation (e.g. POST /v1/rooms.upload/{rid}) when the server answers non-2xx with a non-JSON body (HTML error page, empty body, proxy error), or when the upload transport resolves with { success: false } but no status/error fields.

Common situations: File larger than the server's upload limit (nginx client_max_body_size or Rocket.Chat FileUpload_MaxFileSize), expired auth token yielding an HTML login redirect instead of JSON, reverse proxy or CORS interference on large multipart bodies, or a custom endpoint that returns a bare { success: false }.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/2c21a82813e96649. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/client/hooks/useEndpointUploadMutation.ts:30

	const sendData = useUpload(endpoint as PathFor<'POST'>);
	const dispatchToastMessage = useToastMessageDispatch();

	return useMutation({
		mutationFn: async (formData: FormData): Promise<TData> => {
			const data = sendData(formData);
			const promise = data instanceof Promise ? data : data.promise;
			const result = await promise;

			if (!result.success) {
				if (result.status) {
					throw new Error(result.status);
				}

				if (typeof result.error === 'string') {
					throw new Error(result.error);
				}

				throw new Error(t('FileUpload_Error'));
			}
			return result as TData;
		},
		onError: (error) => {
			dispatchToastMessage({ type: 'error', message: error });
		},
		...options,
	});
};

View on GitHub (pinned to b2c16d5842)