{"record":{"id":"045575f369824c41","repo":"danny-avila/LibreChat","slug":"invalid-input-type-expected-url-buffer-or-file","errorCode":null,"errorMessage":"Invalid input type. Expected URL, Buffer, or File.","messagePattern":"Invalid input type\\. Expected URL, Buffer, or File\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/server/services/Files/images/avatar.js","lineNumber":107,"sourceCode":" * @throws {Error} Throws an error if the user ID is undefined, the input type is invalid, the image fetching fails,\n *                 or any other error occurs during the processing.\n */\nasync function resizeAvatar({ userId, input, desiredFormat = EImageOutputType.PNG, fetchOptions }) {\n  try {\n    if (userId === undefined) {\n      throw new Error('User ID is undefined');\n    }\n\n    let imageBuffer;\n    if (typeof input === 'string') {\n      imageBuffer = await fetchAvatarBuffer(input, fetchOptions);\n    } else if (input instanceof Buffer) {\n      imageBuffer = input;\n    } else if (typeof input === 'object' && input instanceof File) {\n      const fileContent = await fs.readFile(input.path);\n      imageBuffer = Buffer.from(fileContent);\n    } else {\n      throw new Error('Invalid input type. Expected URL, Buffer, or File.');\n    }\n\n    const metadata = await sharp(imageBuffer).metadata();\n    const { width, height } = metadata;\n    const minSize = Math.min(width, height);\n\n    if (metadata.format === 'gif') {\n      const resizedBuffer = await sharp(imageBuffer, { animated: true })\n        .extract({\n          left: Math.floor((width - minSize) / 2),\n          top: Math.floor((height - minSize) / 2),\n          width: minSize,\n          height: minSize,\n        })\n        .resize(250, 250)\n        .gif()\n        .toBuffer();\n","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/server/services/Files/images/avatar.js#L89-L125","documentation":"Thrown by the input-type dispatch in the avatar uploader when `input` is none of: string (treated as URL), Buffer (raw bytes), or a File object (with a `.path`). This is the fallback else-branch after all three supported input shapes are checked. It prevents passing arbitrary objects (e.g., a plain object, a number, a ReadStream) into sharp(), which would produce a confusing downstream error.","triggerScenarios":"Calling uploadAvatar with `input` that is a plain object, number, boolean, ReadStream, ArrayBuffer, Uint8Array (not a Buffer), or a front-end FormData value that wasn't materialized into a File. Also passing `null` or `undefined` after a preceding check expects a different shape.","commonSituations":"Frontend sending a JSON-serialized blob instead of multipart FormData; an integration passing a `Uint8Array` from a browser API instead of converting to Buffer; misrouted call where the caller assumed uploadAvatar accepts a ReadStream.","solutions":["Ensure `input` is one of: a URL string, a Node Buffer, or an Express/Multer File object.","Convert browser `Uint8Array`/`ArrayBuffer` via `Buffer.from(uint8)` before calling.","For form uploads, route through the request's `req.file` (Multer) so a File object is passed.","Add a TypeScript discriminated union on the input parameter to catch mismatches at compile time."],"exampleFix":"// before\nawait uploadAvatar({ userId, input: { data: bytes } });\n\n// after\nawait uploadAvatar({ userId, input: Buffer.from(bytes) });","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"/** @param {unknown} i */\nfunction isValidAvatarInput(i) {\n  if (typeof i === 'string') return true;\n  if (Buffer.isBuffer(i)) return true;\n  return typeof i === 'object' && i !== null && 'path' in i && typeof i.path === 'string';\n}","tryCatchPattern":"try { await uploadAvatar({ userId, input }); }\ncatch (e) {\n  if (/Invalid input type/.test(e.message)) return res.status(400).json({ error: 'Avatar must be a URL, Buffer, or File.' });\n  throw e;\n}","preventionTips":["Type the uploadAvatar `input` parameter as a discriminated union so TS catches misuse at compile time.","Convert browser ArrayBuffer/Uint8Array via Buffer.from before sending.","For multipart uploads, pass the Multer File (req.file) directly."],"tags":["avatar","input-validation","type-dispatch"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}