RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-file

error-invalid-file

Error message

Invalid file

What it means

sendFileMessage first validates the client-supplied file object with validateFileRequiredFields: each of _id, name, type and size must be present as a key. If any is missing it throws error-invalid-file before any database access, so this failure never depends on server state.

Source

Thrown at apps/meteor/server/meteor-methods/messages/sendFileMessage.ts:29

import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Rooms, Uploads, Users } from '@rocket.chat/models';
import { Match, check } from 'meteor/check';
import { Meteor } from 'meteor/meteor';

import { executeSendMessage } from './sendMessage';
import { getFileExtension } from '../../../lib/utils/getFileExtension';
import { canAccessRoomAsync } from '../../lib/authorization/canAccessRoom';
import { callbacks } from '../../lib/callbacks';
import { methodDeprecationLogger } from '../../lib/deprecationWarningLogger';
import { SystemLogger } from '../../lib/logger/system';
import { isImagePreviewSupported } from '../../lib/media/file-upload/isImagePreviewSupported';
import { FileUpload } from '../../lib/media/file-upload/lib/FileUpload';

function validateFileRequiredFields(file: Partial<IUpload>): asserts file is AtLeast<IUpload, '_id' | 'name' | 'type' | 'size'> {
	const requiredFields = ['_id', 'name', 'type', 'size'];
	requiredFields.forEach((field) => {
		if (!Object.keys(file).includes(field)) {
			throw new Meteor.Error('error-invalid-file', 'Invalid file');
		}
	});
}

export const parseFileIntoMessageAttachments = async (
	file: Partial<IUpload>,
	roomId: string,
	user: IUser,
): Promise<FilesAndAttachments> => {
	validateFileRequiredFields(file);

	const upload = await Uploads.findOneByIdAndUserIdAndRoomId(file._id, user._id, roomId, { projection: { _id: 1 } });
	if (!upload) {
		throw new Meteor.Error('error-invalid-file', 'Invalid file', {
			method: 'sendFileMessage',
		});
	}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Pass the complete upload record produced by the upload flow - it contains _id, name, type and size
  2. Validate the object client-side before the method call (see type guard)
  3. Prefer the REST flow POST /v1/rooms.media/:rid followed by POST /v1/rooms.mediaConfirm/:rid/:fileId; the Meteor method is deprecated since 9.0.0

Example fix

// before: partial object
Meteor.call('sendFileMessage', rid, store, { _id: fileId, name: 'log.txt' });

// after: full record from the completed upload
Meteor.call('sendFileMessage', rid, store, {
	_id: upload.fileId,
	name: upload.name,
	type: upload.type,
	size: upload.size,
});
Defensive patterns

Strategy: type-guard

Type guard

import type { IUpload } from '@rocket.chat/core-typings';

type CompleteUpload = Pick<IUpload, '_id' | 'name' | 'type' | 'size'>;

const isCompleteUpload = (
	file: Partial<IUpload>,
): file is CompleteUpload =>
	typeof file._id === 'string' &&
	typeof file.name === 'string' &&
	typeof file.type === 'string' &&
	typeof file.size === 'number';

if (!isCompleteUpload(file)) {
	throw new Error('file payload incomplete');
}
await Meteor.callAsync('sendFileMessage', rid, store, file);

Try / catch

try {
	await Meteor.callAsync('sendFileMessage', rid, store, file);
} catch (e: any) {
	if (e?.error === 'error-invalid-file' && !isCompleteUpload(file)) {
		// client-side payload bug: fix the object, do not retry as-is
	}
	throw e;
}

Prevention

When it happens

Trigger: Meteor.call('sendFileMessage', rid, store, file) with a partial object, e.g. omitting type or size; passing a raw File/Blob handle or a picked subset of the upload record; a refactor or serializer that drops falsy fields (size 0, empty name) from the payload.

Common situations: Client sends a hand-built object instead of the record returned by the completed upload; form data mangled by a middleware; falsy-value filtering (size === 0) accidentally removing required keys.

Related errors


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