{"record":{"id":"caefe6c53d0069f2","repo":"RocketChat/Rocket.Chat","slug":"invalid-file-caefe6","errorCode":"invalid-file","errorMessage":"File is not valid","messagePattern":"File is not valid","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/ufs/ufs-methods.ts","lineNumber":35,"sourceCode":"\t\tthrow new Meteor.Error('invalid-store', 'Store not found');\n\t}\n\n\tconst tmpFile = UploadFS.getTempFilePath(fileId);\n\n\tconst removeTempFile = () =>\n\t\tfs.promises.unlink(tmpFile).catch(() => {\n\t\t\tconsole.warn(`[ufsComplete] Failed to remove temp file: ${tmpFile}`);\n\t\t});\n\n\treturn new Promise(async (resolve, reject) => {\n\t\ttry {\n\t\t\t// todo check if temp file exists\n\n\t\t\t// Get file\n\t\t\tconst file = await store.getCollection().findOne<IUpload>({ _id: fileId }, { session: options?.session });\n\n\t\t\tif (!file) {\n\t\t\t\tthrow new Meteor.Error('invalid-file', 'File is not valid');\n\t\t\t}\n\n\t\t\t// Validate file before moving to the store\n\t\t\tawait store.validate(file, { session: options?.session });\n\n\t\t\t// Get the temp file\n\t\t\tconst rs = fs.createReadStream(tmpFile, {\n\t\t\t\tflags: 'r',\n\t\t\t\tencoding: undefined,\n\t\t\t\tautoClose: true,\n\t\t\t});\n\n\t\t\t// Clean upload if error occurs\n\t\t\trs.on('error', (err) => {\n\t\t\t\tconsole.error(err);\n\t\t\t\tvoid store.removeById(fileId, { session: options?.session });\n\t\t\t\treject(err);\n\t\t\t});","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/ufs/ufs-methods.ts#L17-L53","documentation":"After resolving a valid store, ufsComplete loads the file metadata document via store.getCollection().findOne({_id: fileId}); no document means Meteor.Error 'invalid-file' ('File is not valid'). The _id passed must exist in that store's collection (rocketchat_uploads for the Uploads store) — the upload record is created when the upload starts, so a missing record means the upload never started, was deleted, or belongs to a different store.","triggerScenarios":"ufsComplete called with a fileId that has no record in the store's collection: fabricated id, record deleted mid-upload, or the file was uploaded to a different store than storeName claims.","commonSituations":"Client lost the upload session and retried complete with a stale id; uploads collection cleaned by retention/prune jobs between upload and complete; mismatched storeName/fileId pairs in custom clients.","solutions":["Verify the id exists first: db.rocketchat_uploads.findOne({_id: fileId}) (or the store's collection).","Restart the upload (ufsCreate) to obtain a fresh fileId instead of completing a dead one.","Ensure prune/retention jobs are not deleting in-flight uploads; pass the storeName returned by ufsCreate."],"exampleFix":"// before\nawait Meteor.callAsync('ufsComplete', fileId, 'Uploads');\n\n// after: validate before completing\nconst file = await Meteor.callAsync('getFileRecord', fileId); // or check collection\nif (!file) {\n  // restart upload flow: ufsCreate -> upload chunks -> ufsComplete\n}","handlingStrategy":"validation","validationCode":"const file = await UploadFS.getStore(storeName).getCollection().findOne({ _id: fileId });\nif (!file) {\n  // restart the upload instead of completing\n  return startUpload();\n}","typeGuard":null,"tryCatchPattern":"try { await ufsComplete(fileId, storeName); } catch (e) { if (isMeteorError(e, 'invalid-file')) { /* re-create upload */ return restartUpload(); } throw e; }","preventionTips":["Complete uploads promptly after the last chunk.","Do not reuse fileIds across uploads/sessions.","Ensure retention jobs skip in-flight upload records."],"tags":["rocket-chat","file-upload","ufs","meteor"],"backgroundTag":"missing-file-record","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}