RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-file
error-invalid-file
Error message
Invalid file
What it means
Thrown when Uploads.findOneById(fileID) returns null: no Uploads document exists for the given id. By this point the method already established that no message references the file and that the caller is a valid user; the missing Uploads record is what fails. Deletion via this method only works for files tracked in the Uploads collection.
Source
Thrown at apps/meteor/server/meteor-methods/messages/deleteFileMessage.ts:45
}
check(fileID, String);
const msg = await Messages.getMessageByFileId(fileID);
if (msg) {
return deleteMessageValidatingPermission(msg, userId);
}
const user = await Users.findOneById(userId, { projection: { username: 1 } });
if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'deleteFileMessage',
});
}
const file = await Uploads.findOneById(fileID, { projection: { userId: 1, rid: 1, expiresAt: 1, uploadedAt: 1 } });
if (!file) {
throw new Meteor.Error('error-invalid-file', 'Invalid file', {
method: 'deleteFileMessage',
});
}
if (!(await Upload.canDeleteFile(user, file, null))) {
throw new Meteor.Error('error-not-authorized', 'Not authorized', {
method: 'deleteFileMessage',
});
}
return FileUpload.getStore('Uploads').deleteById(fileID);
},
});
View on GitHub (pinned to b2c16d5842)
Solutions
- Re-verify the file id against a current Uploads record (refresh the file list) before deleting
- Make the flow idempotent: on 'error-invalid-file' during a retry, treat the file as already deleted and refresh UI state
- If Uploads records and the physical store disagree, reconcile the Uploads collection with the store (the standard delete path removes derivatives like thumbnails too)
- Prefer the supported REST path /v1/chat.delete for message-bound deletions
Example fix
// before
await Meteor.callAsync('deleteFileMessage', fileID);
// after — tolerate already-deleted files
try {
await Meteor.callAsync('deleteFileMessage', fileID);
} catch (e) {
if (e.error === 'error-invalid-file') {
// already gone: update local state as deleted, do not retry
} else {
throw e;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
const file = message?.files?.find((f) => f._id === fileID);
if (!file) {
// id not referenced by any known message: refresh data before deleting
return;
}
Meteor.call('deleteFileMessage', fileID); Try / catch
try {
await Meteor.callAsync('deleteFileMessage', fileID);
} catch (e) {
if ((e as Meteor.Error).error === 'error-invalid-file') {
// already deleted / unknown id: mark as removed locally, stop retrying
} else {
throw e;
}
} Prevention
- Single-flight the delete action so the same id cannot be submitted twice concurrently
- Pass ids straight from server payloads without manual transformation
- Treat delete as idempotent in the UI: absorb 'error-invalid-file' on retry
When it happens
Trigger: Meteor.call('deleteFileMessage', fileID) with a mistyped id, a file whose Uploads record was already removed (earlier delete partially completed), or a file id copied from a different database/workspace.
Common situations: Double-click / double-submission of a delete button (second call finds nothing); ids transplanted between environments; Uploads and the GridFS store out of sync after an interrupted delete or partial migration.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/7075f5dc2cd7de89.
Report an issue: GitHub.