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

  1. Send multipart/form-data with the file part named exactly 'file'
  2. Confirm Content-Type is multipart/form-data with a boundary (let FormData set it, do not hardcode without boundary)
  3. Guard client-side: only fire the request when a file is actually selected
  4. 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

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


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)