{"record":{"id":"4ce00d8b41ef5621","repo":"FlowiseAI/Flowise","slug":"must-provide-at-least-one-loader","errorCode":null,"errorMessage":"Must provide at least one loader","messagePattern":"Must provide at least one loader","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/documentloaders/File/File.ts","lineNumber":367,"sourceCode":"    }\n\n    if (processRaw) {\n        return files.length ? JSON.stringify(files) : ''\n    }\n\n    return files.length ? `FILE-STORAGE::${JSON.stringify(files)}` : ''\n}\n\ninterface LoadersMapping {\n    [extension: string]: (blob: Blob) => BaseDocumentLoader\n}\n\nclass MultiFileLoader extends BaseDocumentLoader {\n    constructor(public fileBlobs: { blob: Blob; ext: string }[], public loaders: LoadersMapping) {\n        super()\n\n        if (Object.keys(loaders).length === 0) {\n            throw new Error('Must provide at least one loader')\n        }\n    }\n\n    public async load(): Promise<Document[]> {\n        const documents: Document[] = []\n\n        for (const fileBlob of this.fileBlobs) {\n            const loaderFactory = this.loaders[fileBlob.ext]\n            if (loaderFactory) {\n                const loader = loaderFactory(fileBlob.blob)\n                documents.push(...(await loader.load()))\n            } else {\n                const loader = new TextLoader(fileBlob.blob)\n                try {\n                    documents.push(...(await loader.load()))\n                } catch (error) {\n                    throw new Error(`Error loading file`)\n                }","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/documentloaders/File/File.ts#L349-L385","documentation":"MultiFileLoader constructor asserts that the per-extension loader map is non-empty. This is a programming/contract error by the caller wiring up File_DocumentLoaders, not an end-user input error. If no extension->loader factory is registered, the loader would silently fall back to TextLoader for everything, which the constructor forbids.","triggerScenarios":"File_DocumentLoaders was instantiated with an empty loaders mapping; a refactor pruned all registered extensions; the mapping was built dynamically and a filter removed every entry.","commonSituations":"Code change that accidentally passes {} as the loaders argument; conditional registration logic evaluated false for every extension at runtime.","solutions":["Inspect the caller in File_DocumentLoaders.init and confirm the loaders object passed to MultiFileLoader has at least one extension key.","Ensure required loader imports (Pdf, Docx, Csv, etc.) are not tree-shaken away.","Add a unit test asserting the mapping is populated before constructing MultiFileLoader."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function assertLoadersMapping(loaders: Record<string, unknown>): void {\n  const keys = Object.keys(loaders)\n  if (keys.length === 0) throw new Error('MultiFileLoader requires at least one extension->loader entry')\n  for (const k of keys) {\n    if (typeof loaders[k] !== 'function') throw new Error(`loaders['${k}'] must be a factory function`)\n  }\n}\n// assertLoadersMapping(loaders) before new MultiFileLoader(fileBlobs, loaders)","typeGuard":"function isLoadersMapping(v: unknown): v is Record<string, (b: Blob) => unknown> {\n  if (typeof v !== 'object' || v === null) return false\n  const entries = Object.entries(v)\n  if (entries.length === 0) return false\n  return entries.every(([, fn]) => typeof fn === 'function')\n}","tryCatchPattern":null,"preventionTips":["Always pass a non-empty loaders map; this guard exists to prevent silent TextLoader-everywhere behavior.","Unit-test the wiring of File_DocumentLoaders.init so the mapping is never accidentally empty.","Watch for tree-shaking removing loader imports."],"tags":["validation","configuration","file-loader","programming-error"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}