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
- Pass the complete upload record produced by the upload flow - it contains _id, name, type and size
- Validate the object client-side before the method call (see type guard)
- 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
- Always send the upload record returned by the completed upload, never a hand-built subset
- Type the payload as the required subset so the compiler catches missing fields
- Prefer the REST rooms.media/rooms.mediaConfirm pair over the deprecated method
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
- error-invalid-fields
- error-invalid-query
- error-invalid-file-name
- error-invalid-characters-in-file-name
- error-invalid-data
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/3faac475d2e21e86.
Report an issue: GitHub.