From bb6f8717c314790c8fb0ad55e9c256ecd5900077 Mon Sep 17 00:00:00 2001 From: Sanidhya Singh Date: Sat, 6 Jun 2026 01:35:26 +0530 Subject: [PATCH 1/2] fix: detect uploaded file type for uppercase file extensions mapExtToInputField matched extensions with a case-sensitive switch, so an uppercase extension like ".PDF" fell through to the default 'txtFile' and the uploaded file was handled by the text loader instead of the correct loader (e.g. the PDF loader). Lowercase the extension before matching so file type detection is case-insensitive. Also fix the MIME-type fallback in createFileAttachment: the branch assigned fileInputFieldFromExt (which is always 'txtFile' there) instead of fileInputFieldFromMimeType, so the fallback never selected the field derived from the MIME type. Fixes #5029 --- packages/components/src/utils.test.ts | 34 ++++++++++++++++++- packages/components/src/utils.ts | 2 +- packages/server/src/utils/createAttachment.ts | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/packages/components/src/utils.test.ts b/packages/components/src/utils.test.ts index ba8238ee049..776b5d5252b 100644 --- a/packages/components/src/utils.test.ts +++ b/packages/components/src/utils.test.ts @@ -1,4 +1,10 @@ -import { removeInvalidImageMarkdown, convertRequireToImport, COMMONJS_REQUIRE_REGEX, IMPORT_EXTRACTION_REGEX } from './utils' +import { + removeInvalidImageMarkdown, + convertRequireToImport, + COMMONJS_REQUIRE_REGEX, + IMPORT_EXTRACTION_REGEX, + mapExtToInputField +} from './utils' describe('removeInvalidImageMarkdown', () => { describe('strips non-http/https image markdown', () => { @@ -229,3 +235,29 @@ describe('Import extraction regex (utils.ts line 1596 pattern)', () => { expect(extractModules('console.log("hello")')).toEqual([]) }) }) + +describe('mapExtToInputField', () => { + it('maps known lowercase extensions to their input field', () => { + expect(mapExtToInputField('.pdf')).toBe('pdfFile') + expect(mapExtToInputField('.txt')).toBe('txtFile') + expect(mapExtToInputField('.json')).toBe('jsonFile') + expect(mapExtToInputField('.csv')).toBe('csvFile') + expect(mapExtToInputField('.docx')).toBe('docxFile') + }) + + it('maps uppercase extensions to the same input field (case-insensitive)', () => { + expect(mapExtToInputField('.PDF')).toBe('pdfFile') + expect(mapExtToInputField('.TXT')).toBe('txtFile') + expect(mapExtToInputField('.JSON')).toBe('jsonFile') + expect(mapExtToInputField('.DOCX')).toBe('docxFile') + }) + + it('maps mixed-case extensions to the same input field', () => { + expect(mapExtToInputField('.Pdf')).toBe('pdfFile') + expect(mapExtToInputField('.Csv')).toBe('csvFile') + }) + + it('falls back to txtFile for unknown extensions', () => { + expect(mapExtToInputField('.unknown')).toBe('txtFile') + }) +}) diff --git a/packages/components/src/utils.ts b/packages/components/src/utils.ts index c89210a59f5..729dac983d2 100644 --- a/packages/components/src/utils.ts +++ b/packages/components/src/utils.ts @@ -1072,7 +1072,7 @@ export const getVersion: () => Promise<{ version: string }> = async () => { * @returns {string} */ export const mapExtToInputField = (ext: string) => { - switch (ext) { + switch (ext.toLowerCase()) { case '.txt': return 'txtFile' case '.pdf': diff --git a/packages/server/src/utils/createAttachment.ts b/packages/server/src/utils/createAttachment.ts index 2daec1e2e1d..2cc759c2bf2 100644 --- a/packages/server/src/utils/createAttachment.ts +++ b/packages/server/src/utils/createAttachment.ts @@ -177,7 +177,7 @@ export const createFileAttachment = async (req: Request) => { if (fileInputFieldFromExt !== 'txtFile') { fileInputField = fileInputFieldFromExt } else if (fileInputFieldFromMimeType !== 'txtFile') { - fileInputField = fileInputFieldFromExt + fileInputField = fileInputFieldFromMimeType } await removeSpecificFileFromUpload(file.path ?? file.key) From abc7ea90c354b5edb0cef7f1390d13fa54d64084 Mon Sep 17 00:00:00 2001 From: Sanidhya Singh Date: Sat, 6 Jun 2026 01:40:14 +0530 Subject: [PATCH 2/2] fix: guard mapExtToInputField against nullish extension Use optional chaining so a null/undefined/empty extension falls through to the existing 'txtFile' default instead of throwing on .toLowerCase(), while keeping the string return type intact for callers. --- packages/components/src/utils.test.ts | 6 ++++++ packages/components/src/utils.ts | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/components/src/utils.test.ts b/packages/components/src/utils.test.ts index 776b5d5252b..32529f10fdc 100644 --- a/packages/components/src/utils.test.ts +++ b/packages/components/src/utils.test.ts @@ -260,4 +260,10 @@ describe('mapExtToInputField', () => { it('falls back to txtFile for unknown extensions', () => { expect(mapExtToInputField('.unknown')).toBe('txtFile') }) + + it('falls back to txtFile for empty or nullish extensions', () => { + expect(mapExtToInputField('')).toBe('txtFile') + expect(mapExtToInputField(undefined)).toBe('txtFile') + expect(mapExtToInputField(null as unknown as string)).toBe('txtFile') + }) }) diff --git a/packages/components/src/utils.ts b/packages/components/src/utils.ts index 729dac983d2..da7a58f9da5 100644 --- a/packages/components/src/utils.ts +++ b/packages/components/src/utils.ts @@ -1068,11 +1068,11 @@ export const getVersion: () => Promise<{ version: string }> = async () => { /** * Map Ext to InputField - * @param {string} ext + * @param {string} [ext] File extension (case-insensitive), e.g. ".pdf" * @returns {string} */ -export const mapExtToInputField = (ext: string) => { - switch (ext.toLowerCase()) { +export const mapExtToInputField = (ext?: string) => { + switch (ext?.toLowerCase()) { case '.txt': return 'txtFile' case '.pdf':