{"record":{"id":"fdab5547f3926004","repo":"RocketChat/Rocket.Chat","slug":"error-no-file-uploaded","errorCode":"error-no-file-uploaded","errorMessage":"No file was uploaded","messagePattern":"No file was uploaded","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/rooms.ts","lineNumber":285,"sourceCode":"\t},\n);\n\nAPI.v1.addRoute(\n\t'rooms.media/:rid',\n\t{ authRequired: true },\n\t{\n\t\tasync post() {\n\t\t\tif (!(await canAccessRoomIdAsync(this.urlParams.rid, this.userId))) {\n\t\t\t\treturn API.v1.forbidden();\n\t\t\t}\n\n\t\t\tconst { file, fields } = await MultipartUploadHandler.parseRequest(this.incoming, {\n\t\t\t\tfield: 'file',\n\t\t\t\tmaxSize: settings.get<number>('FileUpload_MaxFileSize'),\n\t\t\t});\n\n\t\t\tif (!file) {\n\t\t\t\tthrow new Meteor.Error('error-no-file-uploaded', 'No file was uploaded');\n\t\t\t}\n\n\t\t\tconst expiresAt = new Date();\n\t\t\texpiresAt.setHours(expiresAt.getHours() + 24);\n\n\t\t\tlet content;\n\n\t\t\tif (fields.content) {\n\t\t\t\ttry {\n\t\t\t\t\tcontent = JSON.parse(fields.content);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(e);\n\t\t\t\t\tthrow new Meteor.Error('invalid-field-content');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst details = {\n\t\t\t\tname: file.filename,","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/e4b8178b205510181a96ceefee043d0abcd13e5a/apps/meteor/server/api/v1/rooms.ts#L267-L303","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst form = new FormData();\nform.append('attachment', fs.createReadStream(path)); // wrong field name\nawait fetch(`${api}/rooms.media/${rid}`, { method: 'POST', body: form });\n\n// after\nconst form = new FormData();\nform.append('file', fs.createReadStream(path), { filename: 'report.png' }); // field must be 'file'\nawait fetch(`${api}/rooms.media/${rid}`, { method: 'POST', body: form });","handlingStrategy":"validation","validationCode":"if (!fileBuffer) throw new Error('no file selected');\nconst form = new FormData();\nform.append('file', fileBuffer, filename); // part named exactly 'file'","typeGuard":null,"tryCatchPattern":"try {\n  await fetch(`${api}/rooms.media/${rid}`, { method: 'POST', body: form });\n} catch (e: any) {\n  if (e?.response?.data?.errorType === 'error-no-file-uploaded') {\n    throw new Error('upload form must contain a part named \"file\"');\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["rooms","file-upload","multipart","rest-api"],"backgroundTag":"missing-file-upload","analyzedSha":"e4b8178b205510181a96ceefee043d0abcd13e5a","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}