{"record":{"id":"eae983e8ca5a2dee","repo":"danny-avila/LibreChat","slug":"no-source-found-for-image-file","errorCode":null,"errorMessage":"No source found for image file","messagePattern":"No source found for image file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/app/clients/tools/structured/OpenAIImageTools.js","lineNumber":304,"sourceCode":"          {},\n        );\n\n        for (const file of fetchedFiles) {\n          requestFilesMap[file.file_id] = file;\n          orderedFiles[indexOfMissing[file.file_id]] = file;\n        }\n      }\n      for (const imageFile of orderedFiles) {\n        if (!imageFile) {\n          continue;\n        }\n        /** @type {NodeStream<File>} */\n        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        });","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/api/app/clients/tools/structured/OpenAIImageTools.js#L286-L322","documentation":"Thrown inside the image-edit tool while iterating orderedFiles: each imageFile must resolve to a `source` (which storage strategy owns it), either from `imageFile.source` or the fallback `appFileStrategy` (passed as fields.fileStrategy at tool creation). If both are empty, the tool cannot pick a download strategy and throws.","triggerScenarios":"Editing an image whose Mongo File document has no `source` field AND the tool was created without `fields.fileStrategy` set (so appFileStrategy is undefined). This happens when file_strategy/app fileStrategy resolution failed upstream.","commonSituations":"The FileSources enum value was not persisted on the file document (legacy data, partial migration); the agent controller did not resolve and pass fileStrategy into createOpenAIImageTools; a file from an unsupported/unknown source; refactoring that stopped forwarding fileStrategy from app config.","solutions":["Ensure createOpenAIImageTools receives `fileStrategy` (the app-wide FileSources value) in its fields.","Backfill the `source` field on File documents that are missing it (it should be one of FileSources enum values like local, s3, firebase).","Investigate why the file document was persisted without a source — check the upload path.","Reject edit requests for files lacking a source earlier, with a clearer user-facing message."],"exampleFix":"// before\nconst tools = createOpenAIImageTools({ req, isAgent: true }); // fileStrategy missing\n// file.source also undefined -> 'No source found for image file'\n\n// after\nconst { appConfig } = require('~/server/config');\nconst tools = createOpenAIImageTools({\n  req,\n  isAgent: true,\n  fileStrategy: appConfig.fileStrategy, // e.g. FileSources.s3\n});","handlingStrategy":"validation","validationCode":"function assertEditToolFields(fields = {}) {\n  if (!fields.fileStrategy) {\n    throw new Error('createOpenAIImageTools requires fields.fileStrategy as a fallback source.');\n  }\n}\nfunction assertFilesHaveSource(files, fallback) {\n  for (const f of files) {\n    if (!f.source && !fallback) {\n      throw new Error('File ' + f.file_id + ' has no source and no app fileStrategy set.');\n    }\n  }\n}","typeGuard":"function fileHasSource(file, fallback) {\n  return Boolean(file?.source || fallback);\n}","tryCatchPattern":"try {\n  await imageEditTool.invoke(args);\n} catch (e) {\n  if (/No source found for image file/.test(e.message)) return 'That file cannot be edited (unknown storage).';\n  throw e;\n}","preventionTips":["Always forward appConfig.fileStrategy into createOpenAIImageTools fields.","Persist the `source` (FileSources enum) on every File document at upload time.","Reject edit requests for sourceless files at the API boundary with a clear message."],"tags":["openai-image","file-storage","image-edit","config","file-strategy"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}