{"record":{"id":"5791b5ef5915b027","repo":"danny-avila/LibreChat","slug":"failed-to-get-download-stream-for-image-file","errorCode":null,"errorMessage":"Failed to get download stream for image file","messagePattern":"Failed to get download stream for image file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/app/clients/tools/structured/OpenAIImageTools.js","lineNumber":317,"sourceCode":"        let stream;\n        /** @type {NodeStreamDownloader<File>} */\n        let getDownloadStream;\n        const source = imageFile.source || appFileStrategy;\n        if (!source) {\n          throw new Error('No source found for image file');\n        }\n        if (streamMethods[source]) {\n          getDownloadStream = streamMethods[source];\n        } else {\n          ({ getDownloadStream } = getStrategyFunctions(source));\n          streamMethods[source] = getDownloadStream;\n        }\n        if (!getDownloadStream) {\n          throw new Error(`No download stream method found for source: ${source}`);\n        }\n        stream = await getDownloadStream(req, imageFile.filepath);\n        if (!stream) {\n          throw new Error('Failed to get download stream for image file');\n        }\n        formData.append('image[]', stream, {\n          filename: imageFile.filename,\n          contentType: imageFile.type,\n        });\n      }\n\n      /** @type {import('axios').RawAxiosHeaders} */\n      let headers = {\n        ...formData.getHeaders(),\n      };\n\n      if (process.env.IMAGE_GEN_OAI_AZURE_API_VERSION && process.env.IMAGE_GEN_OAI_BASEURL) {\n        headers['api-key'] = apiKey;\n      } else {\n        headers['Authorization'] = `Bearer ${apiKey}`;\n      }\n","sourceCodeStart":299,"sourceCodeEnd":335,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/app/clients/tools/structured/OpenAIImageTools.js#L299-L335","documentation":"Thrown when getDownloadStream(req, imageFile.filepath) resolves to a falsy value. The strategy lookup succeeded and the method exists, but the underlying storage call did not return a usable stream — typically because the object/file does not exist at the given path or permissions block the read.","triggerScenarios":"Editing an image where the stored `filepath` no longer points to an existing object — file deleted from disk/S3, the bucket object was removed out-of-band, the local file was pruned, the filepath is stale after a storage migration, or credentials lack read permission on the object.","commonSituations":"File record exists in Mongo but the underlying blob was deleted (orphaned metadata); local file cleared by a cleanup job; S3 lifecycle rule deleted the object; filepath stored with a wrong key after migration; expired/revoked storage credentials; container missing the mounted volume for local storage.","solutions":["Verify the object exists at imageFile.filepath in the underlying storage (e.g., `aws s3 ls` for S3, `ls` for local).","If the object is gone, delete the orphaned File metadata or re-upload the image.","Confirm storage credentials/permissions for the configured fileStrategy have read access.","For local storage, ensure the container/process has the data volume mounted and the path is accessible.","Add a preflight check that fetches file metadata and rejects missing objects with a user-facing message."],"exampleFix":"// before — filepath points to a deleted S3 object\nawait imageEditTool.invoke({ prompt: '...', image_ids: ['file-x'] });\n// 'Failed to get download stream for image file'\n\n// after — preflight existence check (S3 example)\nconst { HeadObjectCommand, S3Client } = require('@aws-sdk/client-s3');\ntry {\n  await s3.send(new HeadObjectCommand({ Bucket, Key: file.filepath }));\n} catch {\n  return 'That image is no longer available. Please re-upload it.';\n}\nawait imageEditTool.invoke({ prompt: '...', image_ids: ['file-x'] });","handlingStrategy":"try-catch","validationCode":"async function assertFileReadable(file, fileStrategy) {\n  const source = file.source || fileStrategy;\n  const { getStrategyFunctions } = require('~/server/services/Files/strategies');\n  const { getDownloadStream } = getStrategyFunctions(source);\n  const stream = await getDownloadStream?.(req, file.filepath);\n  if (!stream) throw new Error('Underlying object missing at ' + file.filepath);\n  stream.destroy?.(); // release\n}","typeGuard":"function fileLooksStored(file) {\n  return Boolean(file?.filepath && file?.source);\n}","tryCatchPattern":"try {\n  await imageEditTool.invoke(args);\n} catch (e) {\n  if (/Failed to get download stream/.test(e.message)) {\n    return 'That image is no longer available; please re-upload it.';\n  }\n  throw e;\n}","preventionTips":["Run a reconciliation job that flags File records whose underlying object is missing.","Delete the File metadata when the storage object is removed, to avoid orphans.","Verify storage credentials/permissions on deploy and after rotation.","Add a preflight HEAD request (S3) or fs.access (local) before invoking the edit tool."],"tags":["openai-image","file-storage","image-edit","streaming","missing-file"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}