{"record":{"id":"5ab89968a31f5593","repo":"RocketChat/Rocket.Chat","slug":"invalid-field-content","errorCode":"invalid-field-content","errorMessage":"invalid-field-content","messagePattern":"invalid-field-content","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/api/v1/rooms.ts","lineNumber":294,"sourceCode":"\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,\n\t\t\t\tsize: file.size,\n\t\t\t\ttype: file.mimetype,\n\t\t\t\trid: this.urlParams.rid,\n\t\t\t\tuserId: this.userId,\n\t\t\t\tcontent,\n\t\t\t\texpiresAt,\n\t\t\t};\n\n\t\t\t// TODO: In the future, we should isolate file receival from storage and post-processing.\n\t\t\tconst fileStore = FileUpload.getStore('Uploads');\n\t\t\tconst uploadedFile = await fileStore.insert(details, file.tempFilePath);\n\n\t\t\tuploadedFile.path = FileUpload.getPath(`${uploadedFile._id}/${encodeURI(uploadedFile.name || '')}`);","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/rooms.ts#L276-L312","documentation":"Thrown by POST rooms.upload when the optional 'content' form field is present but JSON.parse fails. The 'content' field lets callers attach structured metadata (e.g. message attachments) alongside the binary file; if supplied it must be valid JSON.","triggerScenarios":"Multipart upload to rooms.upload/:rid where fields.content is set but is malformed JSON — trailing commas, single quotes, unquoted keys, truncated payload, or a non-JSON string.","commonSituations":"Stringifying an object incompletely; passing a hand-written JSON string with a typo; double-encoding (JSON.stringify of an already-stringified value then truncation); locale number formatting leaking into JSON.","solutions":["Build the content value with JSON.stringify(obj) on the client rather than writing JSON by hand.","If you have no structured metadata, omit the 'content' field entirely.","Log the exact content string and run it through a JSON linter to find the syntax error.","Ensure the field isn't being base64'd or URL-encoded twice."],"exampleFix":"// before\nform.append('content', \"{attachments: ['x']}\"); // invalid JSON\n\n// after\nform.append('content', JSON.stringify({ attachments: ['x'] }));","handlingStrategy":"validation","validationCode":"let contentStr: string | undefined;\nif (contentObj !== undefined) {\n  contentStr = JSON.stringify(contentObj);\n  JSON.parse(contentStr); // throws now, not on the server\n}\nif (contentStr) form.append('content', contentStr);","typeGuard":"function isJsonString(s: unknown): boolean {\n  if (typeof s !== 'string') return false;\n  try { JSON.parse(s); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  await rest.post(url, form);\n} catch (e) {\n  if (isMeteorError(e, 'invalid-field-content')) {\n    // re-stringify content via JSON.stringify and retry\n  } else throw e;\n}","preventionTips":["Never hand-write the content JSON — always JSON.stringify.","Omit 'content' when you have no structured metadata.","Lint the string with JSON.parse client-side before sending."],"tags":["file-upload","json","validation","rest-api"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}