RocketChat/Rocket.Chat · error · Meteor.Error
error-no-file-uploaded
error-no-file-uploaded
Error message
No file was uploaded
What it means
Thrown by POST /api/v1/rooms.media/:rid when MultipartUploadHandler.parseRequest finds no part named 'file' in the multipart request body. The handler is configured with field 'file' and enforces FileUpload_MaxFileSize from settings. The request must be a genuine multipart/form-data body containing a file part with exactly that name; access to the room was already verified before this point.
Solutions
- Send multipart/form-data with the file part named exactly 'file'
- Confirm Content-Type is multipart/form-data with a boundary (let FormData set it, do not hardcode without boundary)
- Guard client-side: only fire the request when a file is actually selected
- Compare your raw request (e.g. curl -F file=@photo.png) against the working reference
Example fix
// before
const form = new FormData();
form.append('attachment', fs.createReadStream(path)); // wrong field name
await fetch(`${api}/rooms.media/${rid}`, { method: 'POST', body: form });
// after
const form = new FormData();
form.append('file', fs.createReadStream(path), { filename: 'report.png' }); // field must be 'file'
await fetch(`${api}/rooms.media/${rid}`, { method: 'POST', body: form }); Defensive patterns
Strategy: validation
Validate before calling
if (!fileBuffer) throw new Error('no file selected');
const form = new FormData();
form.append('file', fileBuffer, filename); // part named exactly 'file' Try / catch
try {
await fetch(`${api}/rooms.media/${rid}`, { method: 'POST', body: form });
} catch (e: any) {
if (e?.response?.data?.errorType === 'error-no-file-uploaded') {
throw new Error('upload form must contain a part named "file"');
}
throw e;
} Prevention
- Name the multipart part 'file' in every upload integration
- Only fire the request when a File is actually present
- Smoke-test uploads with curl -F file=@test.png after proxy changes
When it happens
Trigger: POST rooms.media/<rid> where the file part is named attachment, media, or file[] instead of file; sending JSON or an empty body; sending multipart with only the content field; a proxy or client stripping the file part.
Common situations: Custom upload code using a different form field name than the official clients; switching from rooms.upload to rooms.media and missing the field-name requirement; misconfigured reverse proxies mangling multipart bodies; frontends that append the File only when an input is non-empty.
Related errors
- error-message-size-exceeded
- invalid-field-content
- emoji-is-not-image
- error-action-not-allowed
- error-avatar-invalid-content-type
AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18).
Data as JSON: /api/errors/fdab5547f3926004.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/server/api/v1/rooms.ts:285
},
);
API.v1.addRoute(
'rooms.media/:rid',
{ authRequired: true },
{
async post() {
if (!(await canAccessRoomIdAsync(this.urlParams.rid, this.userId))) {
return API.v1.forbidden();
}
const { file, fields } = await MultipartUploadHandler.parseRequest(this.incoming, {
field: 'file',
maxSize: settings.get<number>('FileUpload_MaxFileSize'),
});
if (!file) {
throw new Meteor.Error('error-no-file-uploaded', 'No file was uploaded');
}
const expiresAt = new Date();
expiresAt.setHours(expiresAt.getHours() + 24);
let content;
if (fields.content) {
try {
content = JSON.parse(fields.content);
} catch (e) {
console.error(e);
throw new Meteor.Error('invalid-field-content');
}
}
const details = {
name: file.filename,View on GitHub (pinned to e4b8178b20)