{"record":{"id":"4dae6f12f7e487c4","repo":"RocketChat/Rocket.Chat","slug":"error-avatar-invalid-content-type","errorCode":"error-avatar-invalid-content-type","errorMessage":"Invalid avatar content type","messagePattern":"Invalid avatar content type","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/users/setUserAvatar.ts","lineNumber":170,"sourceCode":"\t\t\t\t\tmsg: 'Not a valid content-type from the provided avatar url',\n\t\t\t\t\tcontentType,\n\t\t\t\t\turl: dataURI,\n\t\t\t\t});\n\t\t\t\tthrow new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${dataURI}`, {\n\t\t\t\t\tfunction: 'setUserAvatar',\n\t\t\t\t\turl: dataURI,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tbuffer: Buffer.from(await response.arrayBuffer()),\n\t\t\t\ttype: response.headers.get('content-type') || '',\n\t\t\t};\n\t\t}\n\n\t\tif (service === 'rest') {\n\t\t\tif (!contentType) {\n\t\t\t\tthrow new Meteor.Error('error-avatar-invalid-content-type', 'Invalid avatar content type', {\n\t\t\t\t\tfunction: 'setUserAvatar',\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tbuffer: typeof dataURI === 'string' ? Buffer.from(dataURI, 'binary') : dataURI,\n\t\t\t\ttype: contentType,\n\t\t\t};\n\t\t}\n\n\t\tconst fileData = RocketChatFile.dataURIParse(dataURI);\n\n\t\treturn {\n\t\t\tbuffer: Buffer.from(fileData.image, 'base64'),\n\t\t\ttype: fileData.contentType,\n\t\t};\n\t})();\n","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/2a7de457074cbb4d4373fbd9a4e5bea292c9c764/apps/meteor/server/lib/users/setUserAvatar.ts#L152-L188","documentation":"When service === 'rest', setUserAvatar passes the payload bytes through as-is and requires the caller to supply an explicit contentType; there is no content sniffing on this path. A missing/falsy contentType throws error-avatar-invalid-content-type before any data is parsed. This is the path used by REST avatar uploads (users.setAvatar with a binary body).","triggerScenarios":"REST avatar upload where the request Content-Type header is missing or was stripped by a proxy and not forwarded into setUserAvatar; programmatic server code calling setUserAvatar(user, buffer, undefined, 'rest').","commonSituations":"Client-side proxy or gateway stripping Content-Type from forwarded requests; custom integrations sending a raw Buffer without specifying its type; multipart handling losing the part's content type before calling the setter.","solutions":["Always send a valid image Content-Type header (e.g. image/png) with avatar upload requests.","In server code using the 'rest' service, pass contentType explicitly as the third argument.","Validate that the value is an image/* type before calling setUserAvatar."],"exampleFix":"// before\nawait setUserAvatar(user, buffer, undefined, 'rest');\n\n// after\nawait setUserAvatar(user, buffer, 'image/png', 'rest');","handlingStrategy":"validation","validationCode":"if (service === 'rest' && (!contentType || !contentType.startsWith('image/'))) {\n  throw new Meteor.Error('error-avatar-invalid-content-type', 'Invalid avatar content type');\n}\nawait setUserAvatar(user, buffer, contentType, 'rest');","typeGuard":"const isImageContentType = (ct?: string | null): ct is string =>\n  typeof ct === 'string' && ct.split(';')[0].trim().toLowerCase().startsWith('image/');","tryCatchPattern":null,"preventionTips":["Always forward the request's Content-Type header when proxying avatar uploads.","Default to a known type (e.g. image/png) only when you actually know the bytes' format.","In server code, never call setUserAvatar with service 'rest' without the contentType argument."],"tags":["avatar","content-type","rest-api","file-upload"],"backgroundTag":"missing-content-type","analyzedSha":"2a7de457074cbb4d4373fbd9a4e5bea292c9c764","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}