RocketChat/Rocket.Chat · error · Error

result.status

Error message

result.status

What it means

Thrown by the useEndpointUploadMutation hook when a file upload completes but the server returns a failed result (success === false) that carries a non-empty `status` string. The UploadResult contract (packages/ui-contexts/src/ServerContext.ts:14) always includes `status`, so the hook treats a truthy status as the most precise error message available and rethrows it. The thrown Error's message is the raw server status string, surfaced to the user via a toast in onError.

Source

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

type UseEndpointUploadOptions<TData extends UploadResult> = Omit<UseMutationOptions<TData, Error, FormData>, 'mutationFn'>;

export const useEndpointUploadMutation = <TPathPattern extends PathPattern, TData extends UploadResult = UploadResult>(
	endpoint: TPathPattern,
	options?: UseEndpointUploadOptions<TData>,
) => {
	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 f9d3ec372b)

Solutions

  1. Inspect the toast text — it equals result.status; match it against known server upload statuses (error-size-limit-exceeded, error-invalid-file, error-invalid-file-type) to find the cause.
  2. Check FileUpload_MaxFileSize and the media-type allow/deny lists in Administration > File Upload; ensure the file is within limits and an allowed MIME type.
  3. Verify the calling user has the permission required by the specific endpoint (e.g. 'edit-other-user-info' for avatars).
  4. Confirm the endpoint path passed to useEndpointUploadMutation is a valid POST upload route and that the FormData field name matches what the route expects.
  5. If the status is generic ('error'), inspect the server logs / network response body for the underlying reason, since the client only echoes the status field.

Example fix

// before: caller ignores the failure cause
const upload = useEndpointUploadMutation('/v1/rooms.upload/:rid');
upload.mutate(formData);

// after: inspect error.message to branch on the server status
try {
  await upload.mutateAsync(formData);
} catch (e) {
  if (e.message.includes('error-size-limit-exceeded')) {
    dispatchToast({ type: 'error', message: t('File_Too_Large') });
  } else {
    dispatchToast({ type: 'error', message: e.message });
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate file size/type against server settings before uploading
const maxBytes = settings.get('FileUpload_MaxFileSize');
const allowedTypes = settings.get('FileUpload_MediaTypeWhiteList');
if (file.size > maxBytes) { throw new Error('error-size-limit-exceeded'); }
if (allowedTypes && !allowedTypes.test(file.type)) { throw new Error('error-invalid-file-type'); }

Type guard

function isFailedUploadResult(r: UploadResult): r is UploadResult & { success: false } {
  return r.success === false;
}

Try / catch

try {
  await upload.mutateAsync(formData);
} catch (e) {
  const reason = (e as Error).message; // equals result.status
  if (reason.includes('error-size-limit-exceeded')) { /* size UX */ }
  else if (reason.includes('error-invalid-file')) { /* type UX */ }
  else { dispatchToast({ type: 'error', message: reason }); }
}

Prevention

When it happens

Trigger: Calling the mutation returned by useEndpointUploadMutation with a FormData whose POST to the upload endpoint (e.g. /api/v1/rooms.upload/:rid, /api/v1/users.setAvatar) is rejected by the server with a JSON body like { success: false, status: 'error' } or a mapped status such as 'error-size-limit-exceeded', 'error-invalid-file', etc. Any truthy status field is thrown verbatim.

Common situations: Uploading a file that exceeds the server's FileUpload_MaxFileSize setting; uploading a MIME type disallowed by FileUpload_MediaTypeWhiteList/BlackList; avatar upload when the user lacks 'pin-message'/'edit-other-user-info' permissions; the apps-engine file-upload interceptor rejecting the payload; the upload being interrupted mid-stream so the server reports a partial/generic 'error' status.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/3d594b9525078f0e. Report an issue: GitHub.