{"record":{"id":"fdf86ebeb044286f","repo":"danny-avila/LibreChat","slug":"failed-to-convert-heic-image-to-jpeg","errorCode":null,"errorMessage":"Failed to convert HEIC image to JPEG","messagePattern":"Failed to convert HEIC image to JPEG","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"client/src/utils/heicConverter.ts","lineNumber":76,"sourceCode":"      quality,\n    });\n\n    // Report conversion completion\n    onProgress?.(0.8);\n\n    // Create a new File object with the converted blob\n    const convertedFile = new File([convertedBlob], file.name.replace(/\\.(heic|heif)$/i, '.jpg'), {\n      type: 'image/jpeg',\n      lastModified: file.lastModified,\n    });\n\n    // Report file creation completion\n    onProgress?.(1.0);\n\n    return convertedFile;\n  } catch (error) {\n    console.error('Error converting HEIC to JPEG:', error);\n    throw new Error('Failed to convert HEIC image to JPEG');\n  }\n};\n\n/**\n * Process a file, converting it from HEIC to JPEG if necessary\n * @param file - The file to process\n * @param quality - JPEG quality for conversion (0-1), default is 0.9\n * @param onProgress - Optional callback to track conversion progress\n * @returns Promise<File> - The processed file (converted if it was HEIC, original otherwise)\n */\nexport const processFileForUpload = async (\n  file: File,\n  quality: number = 0.9,\n  onProgress?: (progress: number) => void,\n): Promise<File> => {\n  const isHEIC = await isHEICFile(file);\n\n  if (isHEIC) {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/client/src/utils/heicConverter.ts#L58-L94","documentation":"Thrown by convertHEICToJPEG in client/src/utils/heicConverter.ts when the wrapped conversion pipeline rejects. The catch swallows the original cause (logged via console.error) and re-throws a generic message, so the real failure — heic-to dynamic import error, libheif decode failure, unsupported HEIC variant, or out-of-memory on large files — is only visible in the browser console. The function is invoked transitively through processFileForUpload whenever isHEICFile returns true.","triggerScenarios":"Uploading a file whose MIME type or extension matches image/heic|heif AND any of: (a) the 'heic-to' dynamic import fails (network/CSP/bundler misconfig), (b) heicTo() rejects on a corrupt or non-conformant HEIC bitstream, (c) the browser runs out of memory decoding a very large image, or (d) WebAssembly support is disabled where libheif needs it.","commonSituations":"iOS users uploading photos in default HEIC format; older browsers or Safari versions with partial HEIC support; a bundler that cannot code-split the heic-to chunk; CSP rules blocking the dynamic import or the wasm blob; files renamed to .heic that are not actually HEIC.","solutions":["Open the browser console — the line logged just above this throw ('Error converting HEIC to JPEG:') carries the underlying cause; fix that first.","If the dynamic import is failing, verify 'heic-to' is in client/package.json and that your bundler emits the lazy chunk on the same origin.","If decode fails on a specific file, reject it client-side after isHEICFile and surface a user-facing message instead of retrying.","For very large images, downscale or cap file size before calling convertHEICToJPEG to avoid OOM.","Wrap the caller of processFileForUpload in try/catch and fall back to uploading the original file or showing an inline error."],"exampleFix":"// before\ntry {\n  await convertHEICToJPEG(file);\n} catch (e) {\n  // opaque error\n}\n\n// after — let the original cause through for diagnosis\n} catch (error) {\n  console.error('Error converting HEIC to JPEG:', error);\n  throw new Error(`Failed to convert HEIC image to JPEG: ${error instanceof Error ? error.message : 'unknown'}`);\n}","handlingStrategy":"try-catch","validationCode":"import { isHEICFile } from '~/utils/heicConverter';\n\nasync function safeProcess(file: File) {\n  if (await isHEICFile(file)) {\n    // best-effort; conversion may still fail inside\n    if (file.size > 25 * 1024 * 1024) {\n      throw new Error('HEIC file too large to convert client-side');\n    }\n  }\n  return file;\n}","typeGuard":"const isFileLike = (v: unknown): v is File =>\n  v != null && typeof v === 'object' && 'name' in v && 'size' in v && 'type' in v;","tryCatchPattern":"try {\n  const processed = await processFileForUpload(file);\n  await upload(processed);\n} catch (error) {\n  if (error instanceof Error && error.message.includes('Failed to convert HEIC')) {\n    showUserError('Could not convert this HEIC image. Try a JPEG or PNG.');\n  } else {\n    throw error;\n  }\n}","preventionTips":["Cap HEIC file size before attempting conversion to avoid browser OOM.","Surface the underlying cause (console.error) to your error reporter so diagnosis is possible.","Offer a PNG/JPEG fallback path in the upload UI when conversion fails."],"tags":["client","image-processing","heic","upload","browser"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}