diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index bae94d46ec0c..b7ec58e1426c 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -2359,16 +2359,16 @@ const CONST = {
     },
 
     FILE_VALIDATION_ERRORS: {
+        FILE_INVALID: 'fileInvalid',
         WRONG_FILE_TYPE: 'wrongFileType',
-        WRONG_FILE_TYPE_MULTIPLE: 'wrongFileTypeMultiple',
         FILE_TOO_LARGE: 'fileTooLarge',
-        FILE_TOO_LARGE_MULTIPLE: 'fileTooLargeMultiple',
         FILE_TOO_SMALL: 'fileTooSmall',
         FILE_CORRUPTED: 'fileCorrupted',
-        FOLDER_NOT_ALLOWED: 'folderNotAllowed',
-        MAX_FILE_LIMIT_EXCEEDED: 'fileLimitExceeded',
         PROTECTED_FILE: 'protectedFile',
+        HEIC_OR_HEIF_IMAGE: 'heicOrHeifImage',
         IMAGE_DIMENSIONS_TOO_LARGE: 'imageDimensionsTooLarge',
+        FOLDER_NOT_ALLOWED: 'folderNotAllowed',
+        MAX_FILE_LIMIT_EXCEEDED: 'maxFileLimitExceeded',
     },
 
     IOS_CAMERA_ROLL_ACCESS_ERROR: 'Access to photo library was denied',
diff --git a/src/hooks/useFilesValidation.tsx b/src/hooks/useFilesValidation.tsx
index b55e59acc470..4ed4903692ec 100644
--- a/src/hooks/useFilesValidation.tsx
+++ b/src/hooks/useFilesValidation.tsx
@@ -7,18 +7,11 @@ import {useFullScreenLoaderActions} from '@components/FullScreenLoaderContext';
 import PDFThumbnail from '@components/PDFThumbnail';
 import Text from '@components/Text';
 import TextLink from '@components/TextLink';
-import {
-    getFileValidationErrorText,
-    hasHeicOrHeifExtension,
-    normalizeFileObject,
-    resizeImageIfNeeded,
-    splitExtensionFromFileName,
-    validateAttachment,
-    validateImageForCorruption,
-} from '@libs/fileDownload/FileUtils';
-import type {ValidateAttachmentOptions} from '@libs/fileDownload/FileUtils';
+import {getFileValidationErrorText, hasHeicOrHeifExtension, resizeImageIfNeeded, splitExtensionFromFileName} from '@libs/fileDownload/FileUtils';
+import type {FileValidationError} from '@libs/fileDownload/FileUtils';
 import convertHeicImage from '@libs/fileDownload/heicConverter';
 import Log from '@libs/Log';
+import validateAttachmentFile from '@libs/validateAttachmentFile';
 import CONST from '@src/CONST';
 import type {FileObject} from '@src/types/utils/Attachment';
 import useLocalize from './useLocalize';
@@ -26,19 +19,21 @@ import useThemeStyles from './useThemeStyles';
 
 const DEFAULT_IS_VALIDATING_RECEIPTS = true;
 
-type ErrorObject = {
-    error: ValueOf<typeof CONST.FILE_VALIDATION_ERRORS>;
-    fileExtension?: string;
-};
-
 type ValidationOptions = {
     isValidatingReceipts?: boolean;
 };
 
+type ValidationState = {
+    isValidatingReceipts: boolean;
+    isValidatingMultipleFiles: boolean;
+};
+
 const sortFilesByOriginalOrder = (files: FileObject[], orderMap: Map<string, number>) => {
     return files.sort((a, b) => (orderMap.get(a.uri ?? '') ?? 0) - (orderMap.get(b.uri ?? '') ?? 0));
 };
 
+const isImageFile = (file: FileObject) => hasHeicOrHeifExtension(file) ?? Str.isImage(file.name ?? '');
+
 function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransferItems: DataTransferItem[]) => void) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -48,11 +43,10 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
     const [isValidatingMultipleFiles, setIsValidatingMultipleFiles] = useState(false);
 
     const [isErrorModalVisible, setIsErrorModalVisible] = useState(false);
-    const [fileError, setFileError] = useState<ValueOf<typeof CONST.FILE_VALIDATION_ERRORS> | null>(null);
+    const [fileError, setFileError] = useState<FileValidationError | null>(null);
     const [pdfFilesToRender, setPdfFilesToRender] = useState<FileObject[]>([]);
     const [validFilesToUpload, setValidFilesToUpload] = useState([] as FileObject[]);
-    const [invalidFileExtension, setInvalidFileExtension] = useState('');
-    const [errorQueue, setErrorQueue] = useState<ErrorObject[]>([]);
+    const [errorQueue, setErrorQueue] = useState<FileValidationError[]>([]);
     const [currentErrorIndex, setCurrentErrorIndex] = useState(0);
     const {setIsLoaderVisible} = useFullScreenLoaderActions();
 
@@ -60,7 +54,7 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
     const validFiles = useRef<FileObject[]>([]);
     const filesToValidate = useRef<FileObject[]>([]);
     const dataTransferItemList = useRef<DataTransferItem[]>([]);
-    const collectedErrors = useRef<ErrorObject[]>([]);
+    const collectedErrors = useRef<FileValidationError[]>([]);
     const originalFileOrder = useRef<Map<string, number>>(new Map());
 
     const updateFileOrderMapping = (oldFile: FileObject | undefined, newFile: FileObject) => {
@@ -70,10 +64,10 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
         }
     };
 
-    const deduplicateErrors = (errors: ErrorObject[]) => {
+    const deduplicateErrors = (errors: FileValidationError[]) => {
         const uniqueErrors = new Set<string>();
         return errors.filter((error) => {
-            const key = `${error.error}-${error.fileExtension ?? ''}`;
+            const key = `${error.error}-${error.fileType ?? ''}`;
             if (uniqueErrors.has(key)) {
                 return false;
             }
@@ -82,16 +76,14 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
         });
     };
 
-    const resetValidationState = () => {
+    const reset = () => {
         setIsValidatingFiles(false);
         setIsValidatingReceipts(undefined);
-        setIsValidatingMultipleFiles(false);
         setIsErrorModalVisible(false);
         setPdfFilesToRender([]);
         setIsLoaderVisible(false);
         setValidFilesToUpload([]);
         setFileError(null);
-        setInvalidFileExtension('');
         setErrorQueue([]);
         setCurrentErrorIndex(0);
         validatedPDFs.current = [];
@@ -106,58 +98,15 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
         setIsErrorModalVisible(false);
         // eslint-disable-next-line @typescript-eslint/no-deprecated
         InteractionManager.runAfterInteractions(() => {
-            resetValidationState();
+            reset();
         });
     };
 
     const setErrorAndOpenModal = (error: ValueOf<typeof CONST.FILE_VALIDATION_ERRORS>) => {
-        setFileError(error);
+        setFileError({error, isValidatingMultipleFiles});
         setIsErrorModalVisible(true);
     };
 
-    const isValidFile = (originalFile: FileObject, item: DataTransferItem | undefined, validationOptions: ValidateAttachmentOptions) => {
-        if (item && item.kind === 'file' && 'webkitGetAsEntry' in item) {
-            const entry = item.webkitGetAsEntry();
-
-            if (entry?.isDirectory) {
-                collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.FOLDER_NOT_ALLOWED});
-                return Promise.resolve(false);
-            }
-        }
-
-        return normalizeFileObject(originalFile)
-            .then((normalizedFile) =>
-                validateImageForCorruption(normalizedFile).then(() => {
-                    const error = validateAttachment(normalizedFile, validationOptions);
-                    if (error) {
-                        const errorData = {
-                            error,
-                            fileExtension: error === CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE_MULTIPLE ? splitExtensionFromFileName(normalizedFile.name ?? '').fileExtension : undefined,
-                        };
-                        collectedErrors.current.push(errorData);
-                        return false;
-                    }
-                    return true;
-                }),
-            )
-            .catch(() => {
-                collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.FILE_CORRUPTED});
-                return false;
-            });
-    };
-
-    const convertHeicToProcessableImagePromise = (file: FileObject): Promise<FileObject> => {
-        return new Promise((resolve) => {
-            convertHeicImage(file, {
-                onSuccess: (convertedFile) => resolve(convertedFile),
-                onError: (_error, originalFile) => {
-                    Log.warn('HEIC conversion failed, falling back to original file', {fileName: file.name});
-                    resolve(originalFile);
-                },
-            });
-        });
-    };
-
     const checkIfAllValidatedAndProceed = () => {
         if (!validatedPDFs.current || !validFiles.current) {
             return;
@@ -177,21 +126,17 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
             setCurrentErrorIndex(0);
             const firstError = uniqueErrors.at(0);
             if (firstError) {
-                setFileError(firstError.error);
-                if (firstError.fileExtension) {
-                    setInvalidFileExtension(firstError.fileExtension);
-                }
+                setFileError(firstError);
                 setIsErrorModalVisible(true);
             }
         } else if (validFiles.current.length > 0) {
             const sortedFiles = sortFilesByOriginalOrder(validFiles.current, originalFileOrder.current);
             onFilesValidated(sortedFiles, dataTransferItemList.current);
-            resetValidationState();
+            reset();
         }
     };
 
-    const validateAndResizeFiles = (files: FileObject[], items: DataTransferItem[], validationOptions?: ValidationOptions) => {
-        // Early return for empty files
+    async function validateAndResizeFiles(files: FileObject[], items: DataTransferItem[], validationState: ValidationState) {
         if (files.length === 0) {
             return;
         }
@@ -203,110 +148,138 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
             originalFileOrder.current.set(file.uri ?? '', index);
         }
 
-        Promise.all(
-            files.map((file, index) =>
-                isValidFile(file, items.at(index), {isValidatingMultipleFiles: files.length > 1, isValidatingReceipts: validationOptions?.isValidatingReceipts ?? isValidatingReceipts}).then(
-                    (isValid) => (isValid ? file : null),
-                ),
-            ),
-        )
-            .then((validationResults) => {
-                const filteredResults = validationResults.filter((result): result is FileObject => result !== null);
-                const pdfsToLoad = filteredResults.filter((file) => Str.isPDF(file.name ?? ''));
-                const otherFiles = filteredResults.filter((file) => !Str.isPDF(file.name ?? ''));
-
-                // Check if we need to convert images
-                if (otherFiles.some((file) => hasHeicOrHeifExtension(file))) {
-                    setIsLoaderVisible(true);
-
-                    return Promise.all(otherFiles.map((file) => convertHeicToProcessableImagePromise(file))).then((convertedImages) => {
-                        for (const [index, convertedFile] of convertedImages.entries()) {
-                            updateFileOrderMapping(otherFiles.at(index), convertedFile);
-                        }
-
-                        // Check if we need to resize images
-                        if (convertedImages.some((file) => (file.size ?? 0) > CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE)) {
-                            return Promise.allSettled(convertedImages.map((file) => resizeImageIfNeeded(file))).then((results) => {
-                                const processedFiles: FileObject[] = [];
-                                for (const [index, result] of results.entries()) {
-                                    if (result.status === 'fulfilled') {
-                                        processedFiles.push(result.value);
-                                        updateFileOrderMapping(convertedImages.at(index), result.value);
-                                    } else {
-                                        const errorMessage = result.reason instanceof Error ? result.reason.message : undefined;
-                                        if (errorMessage === CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE) {
-                                            collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE});
-                                        } else {
-                                            collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.FILE_CORRUPTED});
-                                        }
-                                    }
-                                }
-                                setIsLoaderVisible(false);
-                                return Promise.resolve({processedFiles, pdfsToLoad});
-                            });
-                        }
+        const pdfsToLoad: FileObject[] = [];
+        const validNonPdfFiles: FileObject[] = [];
+
+        const filesToResize: FileObject[] = [];
+        const filesToConvert: FileObject[] = [];
+        await Promise.all(
+            files.map(async (file, index) => {
+                const result = await validateAttachmentFile(file, items.at(index), validationState.isValidatingReceipts);
 
-                        // No resizing needed, just return the converted images
-                        setIsLoaderVisible(false);
-                        return Promise.resolve({processedFiles: convertedImages, pdfsToLoad});
-                    });
+                if (result.isValid) {
+                    if (Str.isPDF(result.file.name ?? '')) {
+                        pdfsToLoad.push(result.file);
+                    } else {
+                        validNonPdfFiles.push(result.file);
+                    }
+                    return;
                 }
 
-                // No conversion needed, but check if we need to resize images
-                if (otherFiles.some((file) => (file.size ?? 0) > CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE)) {
-                    setIsLoaderVisible(true);
-                    return Promise.allSettled(otherFiles.map((file) => resizeImageIfNeeded(file))).then((results) => {
-                        const processedFiles: FileObject[] = [];
-                        for (const [index, result] of results.entries()) {
-                            if (result.status === 'fulfilled') {
-                                processedFiles.push(result.value);
-                                updateFileOrderMapping(otherFiles.at(index), result.value);
-                            } else {
-                                const errorMessage = result.reason instanceof Error ? result.reason.message : undefined;
-                                if (errorMessage === CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE) {
-                                    collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE});
-                                } else {
-                                    collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.FILE_CORRUPTED});
-                                }
-                            }
-                        }
-                        setIsLoaderVisible(false);
-                        return Promise.resolve({processedFiles, pdfsToLoad});
-                    });
+                if (result.error === CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE && isImageFile(file) && validationState.isValidatingReceipts) {
+                    filesToResize.push(file);
+                    return;
                 }
 
-                // No conversion or resizing needed, just return the valid images
-                return Promise.resolve({processedFiles: otherFiles, pdfsToLoad});
-            })
-            .then(({processedFiles, pdfsToLoad}) => {
-                if (pdfsToLoad.length) {
-                    validFiles.current = processedFiles;
-                    setPdfFilesToRender(pdfsToLoad);
-                } else {
-                    if (processedFiles.length > 0) {
-                        setValidFilesToUpload(processedFiles);
-                    }
+                if (result.error === CONST.FILE_VALIDATION_ERRORS.HEIC_OR_HEIF_IMAGE) {
+                    filesToConvert.push(file);
+                    return;
+                }
+
+                const errorData = {
+                    error: result.error,
+                    isValidatingMultipleFiles: validationState.isValidatingMultipleFiles,
+                    fileType: result.error === CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE ? splitExtensionFromFileName(file.name ?? '').fileExtension : undefined,
+                } satisfies FileValidationError;
+                collectedErrors.current.push(errorData);
+            }),
+        );
+
+        if (filesToConvert.length > 0) {
+            setIsLoaderVisible(true);
+
+            const convertedFilesToResize: FileObject[] = [];
+            const convertedFiles: FileObject[] = [];
+            await Promise.all(
+                filesToConvert.map(
+                    (file) =>
+                        new Promise<void>((resolve) => {
+                            convertHeicImage(file, {
+                                onSuccess: (convertedFile) => {
+                                    if (validationState.isValidatingReceipts && convertedFile.size && convertedFile.size > CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE) {
+                                        convertedFilesToResize.push(convertedFile);
+                                        resolve();
+                                        return;
+                                    }
 
-                    if (collectedErrors.current.length > 0) {
-                        const uniqueErrors = Array.from(new Set(collectedErrors.current.map((error) => JSON.stringify(error)))).map((errorStr) => JSON.parse(errorStr) as ErrorObject);
-                        setErrorQueue(uniqueErrors);
-                        setCurrentErrorIndex(0);
-                        const firstError = uniqueErrors.at(0);
-                        if (firstError) {
-                            setFileError(firstError.error);
-                            if (firstError.fileExtension) {
-                                setInvalidFileExtension(firstError.fileExtension);
-                            }
-                            setIsErrorModalVisible(true);
-                        }
-                    } else if (processedFiles.length > 0) {
-                        const sortedFiles = sortFilesByOriginalOrder(processedFiles, originalFileOrder.current);
-                        onFilesValidated(sortedFiles, dataTransferItemList.current);
-                        resetValidationState();
+                                    if (!validationState.isValidatingReceipts && convertedFile.size && convertedFile.size > CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE) {
+                                        collectedErrors.current.push({
+                                            error: CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE,
+                                            isValidatingMultipleFiles: validationState.isValidatingMultipleFiles,
+                                        });
+                                        resolve();
+                                        return;
+                                    }
+
+                                    convertedFiles.push(convertedFile);
+                                    resolve();
+                                },
+                                onError: () => {
+                                    Log.warn('HEIC conversion failed, falling back to original file', {fileName: file.name});
+                                    convertedFiles.push(file);
+                                    resolve();
+                                },
+                            });
+                        }),
+                ),
+            );
+
+            filesToResize.push(...convertedFilesToResize);
+            validNonPdfFiles.push(...convertedFiles);
+
+            for (const [index, convertedFile] of convertedFiles.entries()) {
+                updateFileOrderMapping(filesToConvert.at(index), convertedFile);
+            }
+        }
+
+        if (filesToResize.length > 0) {
+            setIsLoaderVisible(true);
+
+            const toResizeResults = await Promise.allSettled(filesToResize.map((file) => resizeImageIfNeeded(file)));
+
+            for (const [index, result] of toResizeResults.entries()) {
+                if (result.status === 'fulfilled') {
+                    const value = result.value;
+                    validNonPdfFiles.push(value);
+                    updateFileOrderMapping(filesToResize.at(index), value);
+                } else {
+                    const errorMessage = result.reason instanceof Error ? result.reason.message : undefined;
+                    if (errorMessage === CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE) {
+                        collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE, isValidatingMultipleFiles});
+                    } else {
+                        collectedErrors.current.push({error: CONST.FILE_VALIDATION_ERRORS.FILE_CORRUPTED, isValidatingMultipleFiles});
                     }
                 }
-            });
-    };
+            }
+        }
+
+        setIsLoaderVisible(false);
+
+        if (pdfsToLoad.length) {
+            validFiles.current = validNonPdfFiles;
+            setPdfFilesToRender(pdfsToLoad);
+            return;
+        }
+
+        if (validNonPdfFiles.length > 0) {
+            setValidFilesToUpload(validNonPdfFiles);
+        }
+
+        if (collectedErrors.current.length > 0) {
+            const uniqueErrors = Array.from(new Set(collectedErrors.current.map((error) => JSON.stringify(error)))).map((errorStr) => JSON.parse(errorStr) as FileValidationError);
+            setErrorQueue(uniqueErrors);
+            setCurrentErrorIndex(0);
+            const firstError = uniqueErrors.at(0);
+            if (firstError) {
+                setFileError(firstError);
+                setIsErrorModalVisible(true);
+            }
+        } else if (validNonPdfFiles.length > 0) {
+            const sortedFiles = sortFilesByOriginalOrder(validNonPdfFiles, originalFileOrder.current);
+            onFilesValidated(sortedFiles, dataTransferItemList.current);
+            reset();
+        }
+    }
 
     const validateFiles = (files: FileObject[], items?: DataTransferItem[], validationOptions?: ValidationOptions) => {
         if (isValidatingFiles) {
@@ -316,15 +289,13 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
 
         setIsValidatingFiles(true);
 
-        const validationOptionsWithDefaults = {
-            ...validationOptions,
+        const validationState: ValidationState = {
             isValidatingReceipts: validationOptions?.isValidatingReceipts ?? DEFAULT_IS_VALIDATING_RECEIPTS,
+            isValidatingMultipleFiles: files.length > 1,
         };
-        setIsValidatingReceipts(validationOptionsWithDefaults.isValidatingReceipts);
+        setIsValidatingReceipts(validationState.isValidatingReceipts);
+        setIsValidatingMultipleFiles(validationState.isValidatingMultipleFiles);
 
-        if (files.length > 1) {
-            setIsValidatingMultipleFiles(true);
-        }
         if (files.length > CONST.API_ATTACHMENT_VALIDATIONS.MAX_FILE_LIMIT) {
             filesToValidate.current = files.slice(0, CONST.API_ATTACHMENT_VALIDATIONS.MAX_FILE_LIMIT);
             if (items) {
@@ -332,14 +303,18 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
             }
             setErrorAndOpenModal(CONST.FILE_VALIDATION_ERRORS.MAX_FILE_LIMIT_EXCEEDED);
         } else {
-            validateAndResizeFiles(files, items ?? [], validationOptionsWithDefaults);
+            validateAndResizeFiles(files, items ?? [], validationState);
         }
     };
 
     const onConfirmError = () => {
-        if (fileError === CONST.FILE_VALIDATION_ERRORS.MAX_FILE_LIMIT_EXCEEDED) {
+        if (fileError?.error === CONST.FILE_VALIDATION_ERRORS.MAX_FILE_LIMIT_EXCEEDED) {
             setIsErrorModalVisible(false);
-            validateAndResizeFiles(filesToValidate.current, dataTransferItemList.current);
+            const validationState: ValidationState = {
+                isValidatingReceipts: isValidatingReceipts ?? false,
+                isValidatingMultipleFiles,
+            };
+            validateAndResizeFiles(filesToValidate.current, dataTransferItemList.current, validationState);
             return;
         }
 
@@ -351,8 +326,7 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
                     setIsValidatingMultipleFiles(false);
                 }
                 setCurrentErrorIndex(nextIndex);
-                setFileError(nextError.error);
-                setInvalidFileExtension(nextError.fileExtension ?? '');
+                setFileError(nextError);
                 return;
             }
         }
@@ -367,7 +341,7 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
                 if (sortedFiles.length !== 0) {
                     onFilesValidated(sortedFiles, dataTransferItemList.current);
                 }
-                resetValidationState();
+                reset();
             });
         } else {
             if (sortedFiles.length !== 0) {
@@ -406,12 +380,14 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
           ))
         : undefined;
 
+    const fileValidationErrorText = getFileValidationErrorText(translate, fileError, {isValidatingReceipt: isValidatingReceipts});
+
     const getModalPrompt = () => {
         if (!fileError) {
             return '';
         }
-        const prompt = getFileValidationErrorText(translate, fileError, {fileType: invalidFileExtension}, isValidatingReceipts === true).reason;
-        if (fileError === CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE_MULTIPLE || fileError === CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE) {
+        const prompt = fileValidationErrorText.reason;
+        if (fileError.error === CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE) {
             return (
                 <Text>
                     {prompt}
@@ -424,7 +400,7 @@ function useFilesValidation(onFilesValidated: (files: FileObject[], dataTransfer
 
     const ErrorModal = (
         <ConfirmModal
-            title={getFileValidationErrorText(translate, fileError, {fileType: invalidFileExtension}, isValidatingReceipts === true).title}
+            title={fileValidationErrorText.title}
             onConfirm={onConfirmError}
             onCancel={hideModalAndReset}
             isVisible={isErrorModalVisible}
diff --git a/src/libs/AttachmentUtils.ts b/src/libs/AttachmentUtils.ts
index f6cfa7ff0675..674dffa21b0f 100644
--- a/src/libs/AttachmentUtils.ts
+++ b/src/libs/AttachmentUtils.ts
@@ -1,106 +1,4 @@
 import CONST from '@src/CONST';
-import type {FileObject} from '@src/types/utils/Attachment';
-import {cleanFileName, validateImageForCorruption} from './fileDownload/FileUtils';
-
-type AttachmentValidationError = CorruptionError | 'fileDoesNotExist' | 'fileInvalid';
-type ValidResult = {
-    isValid: true;
-    fileType: 'file' | 'uri';
-    source: string;
-    file: FileObject;
-};
-type InvalidResult = {
-    isValid: false;
-    error: AttachmentValidationError;
-};
-
-type AttachmentValidationResult = ValidResult | InvalidResult;
-
-function validateAttachmentFile(file: FileObject): Promise<AttachmentValidationResult> {
-    if (!file || !isDirectoryCheck(file)) {
-        return Promise.resolve({isValid: false, error: 'fileDoesNotExist'});
-    }
-
-    let fileObject = file;
-    const fileConverted = file.getAsFile?.();
-    if (fileConverted) {
-        fileObject = fileConverted;
-    }
-    if (!fileObject) {
-        return Promise.resolve({isValid: false, error: 'fileInvalid'});
-    }
-
-    return isFileCorrupted(fileObject).then((corruptionResult) => {
-        if (!corruptionResult.isValid) {
-            return corruptionResult as InvalidResult;
-        }
-
-        if (fileObject instanceof File) {
-            /**
-             * Cleaning file name, done here so that it covers all cases:
-             * upload, drag and drop, copy-paste
-             */
-            let updatedFile = fileObject;
-            const cleanName = cleanFileName(updatedFile.name);
-            if (updatedFile.name !== cleanName) {
-                updatedFile = new File([updatedFile], cleanName, {type: updatedFile.type});
-            }
-            const inputSource = URL.createObjectURL(updatedFile);
-            updatedFile.uri = inputSource;
-
-            return {isValid: true, fileType: 'file', source: inputSource, file: updatedFile} as ValidResult;
-        }
-
-        return {isValid: true, fileType: 'uri', source: fileObject.uri, file: fileObject} as ValidResult;
-    });
-}
-
-type CorruptionError = 'tooLarge' | 'tooSmall' | 'error';
-type NoCorruptionResult = {
-    isValid: true;
-};
-type CorruptionResult = {
-    isValid: false;
-    error: CorruptionError;
-};
-type AttachmentCorruptionValidationResult = NoCorruptionResult | CorruptionResult;
-
-function isFileCorrupted(fileObject: FileObject): Promise<AttachmentCorruptionValidationResult> {
-    return validateImageForCorruption(fileObject)
-        .then(() => {
-            if (fileObject.size && fileObject.size > CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE) {
-                return {
-                    isValid: false,
-                    error: 'tooLarge',
-                } satisfies AttachmentCorruptionValidationResult;
-            }
-
-            if (fileObject.size && fileObject.size < CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE) {
-                return {
-                    isValid: false,
-                    error: 'tooSmall',
-                } satisfies AttachmentCorruptionValidationResult;
-            }
-
-            return {
-                isValid: true,
-            } satisfies AttachmentCorruptionValidationResult;
-        })
-        .catch(() => {
-            return {
-                isValid: false,
-                error: 'error',
-            };
-        });
-}
-
-function isDirectoryCheck(data: FileObject) {
-    if ('webkitGetAsEntry' in data && (data as DataTransferItem).webkitGetAsEntry()?.isDirectory) {
-        return false;
-    }
-
-    return true;
-}
 
 /**
  * Returns image cache file extension based from mime type
@@ -110,5 +8,5 @@ function getImageCacheFileExtension(contentType: string) {
     return imageCacheFileTypes[contentType] ?? '';
 }
 
-export {validateAttachmentFile, getImageCacheFileExtension};
-export type {AttachmentValidationResult};
+// eslint-disable-next-line import/prefer-default-export
+export {getImageCacheFileExtension};
diff --git a/src/libs/fileDownload/FileUtils.ts b/src/libs/fileDownload/FileUtils.ts
index 9c6fb7417a19..385f429b2f31 100644
--- a/src/libs/fileDownload/FileUtils.ts
+++ b/src/libs/fileDownload/FileUtils.ts
@@ -644,9 +644,9 @@ const hasHeicOrHeifExtension = (file: FileObject) => {
  * Otherwise, it attempts to fetch the file via its URI and reconstruct a File
  * with full metadata (name, size, type).
  */
-const normalizeFileObject = (file: FileObject): Promise<FileObject> => {
+const normalizeFileObject = async (file: FileObject): Promise<FileObject> => {
     if (file instanceof File || file instanceof Blob) {
-        return Promise.resolve(file);
+        return file;
     }
 
     const isAndroidNative = getPlatform() === CONST.PLATFORM.ANDROID;
@@ -654,61 +654,34 @@ const normalizeFileObject = (file: FileObject): Promise<FileObject> => {
     const isNativePlatform = isAndroidNative || isIOSNative;
 
     if (!isNativePlatform || 'size' in file) {
-        return Promise.resolve(file);
+        return file;
     }
 
     if (typeof file.uri !== 'string') {
-        return Promise.resolve(file);
+        return file;
     }
 
-    return fetch(file.uri)
-        .then((response) => response.blob())
-        .then((blob) => {
-            const name = file.name ?? 'unknown';
-            const type = file.type ?? blob.type ?? 'application/octet-stream';
-            const normalizedFile = new File([blob], name, {type});
-            return normalizedFile;
-        })
-        .catch((error) => {
-            return Promise.reject(error);
-        });
+    const response = await fetch(file.uri);
+    const blob = await response.blob();
+    const name = file.name ?? 'unknown';
+    const type = file.type ?? blob.type ?? 'application/octet-stream';
+    return new File([blob], name, {type});
 };
 
-type ValidateAttachmentOptions = {
-    isValidatingReceipts?: boolean;
+type FileValidationError = {
+    error: ValueOf<typeof CONST.FILE_VALIDATION_ERRORS>;
     isValidatingMultipleFiles?: boolean;
+    fileType?: string;
 };
 
-const validateAttachment = (file: FileObject, validationOptions?: ValidateAttachmentOptions) => {
-    const maxFileSize = validationOptions?.isValidatingReceipts ? CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE : CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE;
-
-    if (validationOptions?.isValidatingReceipts && !isValidReceiptExtension(file)) {
-        return validationOptions?.isValidatingMultipleFiles ? CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE_MULTIPLE : CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE;
-    }
-
-    // Images are exempt from file size check since they will be resized
-    if (!Str.isImage(file.name ?? '') && !hasHeicOrHeifExtension(file) && (file?.size ?? 0) > maxFileSize) {
-        return validationOptions?.isValidatingMultipleFiles ? CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE_MULTIPLE : CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE;
-    }
-
-    if (validationOptions?.isValidatingReceipts && (file?.size ?? 0) < CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE) {
-        return CONST.FILE_VALIDATION_ERRORS.FILE_TOO_SMALL;
-    }
-
-    return '';
-};
-
-type TranslationAdditionalData = {
-    maxUploadSizeInMB?: number;
-    fileLimit?: number;
-    fileType?: string;
+type GetFileValidationErrorTextOptions = {
+    isValidatingReceipt?: boolean;
 };
 
 const getFileValidationErrorText = (
     translate: LocalizedTranslate,
-    validationError: ValueOf<typeof CONST.FILE_VALIDATION_ERRORS> | null,
-    additionalData: TranslationAdditionalData = {},
-    isValidatingReceipt = false,
+    validationError: FileValidationError | null,
+    options: GetFileValidationErrorTextOptions = {},
 ): {
     title: string;
     reason: string;
@@ -719,45 +692,51 @@ const getFileValidationErrorText = (
             reason: '',
         };
     }
-    const maxSize = isValidatingReceipt ? CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE : CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE;
-    switch (validationError) {
+    const maxSize = options.isValidatingReceipt ? CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE : CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE;
+
+    if (validationError.isValidatingMultipleFiles) {
+        switch (validationError.error) {
+            case CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE:
+                return {
+                    title: translate('attachmentPicker.someFilesCantBeUploaded'),
+                    reason: translate('attachmentPicker.unsupportedFileType', validationError.fileType ?? ''),
+                };
+            case CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE:
+                return {
+                    title: translate('attachmentPicker.someFilesCantBeUploaded'),
+                    reason: translate('attachmentPicker.sizeLimitExceeded', maxSize / 1024 / 1024),
+                };
+            case CONST.FILE_VALIDATION_ERRORS.FOLDER_NOT_ALLOWED:
+                return {
+                    title: translate('attachmentPicker.attachmentError'),
+                    reason: translate('attachmentPicker.folderNotAllowedMessage'),
+                };
+            case CONST.FILE_VALIDATION_ERRORS.MAX_FILE_LIMIT_EXCEEDED:
+                return {
+                    title: translate('attachmentPicker.someFilesCantBeUploaded'),
+                    reason: translate('attachmentPicker.maxFileLimitExceeded'),
+                };
+            default:
+                break;
+        }
+    }
+
+    switch (validationError.error) {
         case CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE:
             return {
                 title: translate('attachmentPicker.wrongFileType'),
                 reason: translate('attachmentPicker.notAllowedExtension'),
             };
-        case CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE_MULTIPLE:
-            return {
-                title: translate('attachmentPicker.someFilesCantBeUploaded'),
-                reason: translate('attachmentPicker.unsupportedFileType', additionalData.fileType ?? ''),
-            };
         case CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE:
             return {
                 title: translate('attachmentPicker.attachmentTooLarge'),
-                reason: isValidatingReceipt
-                    ? translate('attachmentPicker.sizeExceededWithLimit', additionalData.maxUploadSizeInMB ?? CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE / 1024 / 1024)
-                    : translate('attachmentPicker.sizeExceeded'),
-            };
-        case CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE_MULTIPLE:
-            return {
-                title: translate('attachmentPicker.someFilesCantBeUploaded'),
-                reason: translate('attachmentPicker.sizeLimitExceeded', additionalData.maxUploadSizeInMB ?? maxSize / 1024 / 1024),
+                reason: options.isValidatingReceipt ? translate('attachmentPicker.sizeExceededWithLimit', maxSize / 1024 / 1024) : translate('attachmentPicker.sizeExceeded'),
             };
         case CONST.FILE_VALIDATION_ERRORS.FILE_TOO_SMALL:
             return {
                 title: translate('attachmentPicker.attachmentTooSmall'),
                 reason: translate('attachmentPicker.sizeNotMet'),
             };
-        case CONST.FILE_VALIDATION_ERRORS.FOLDER_NOT_ALLOWED:
-            return {
-                title: translate('attachmentPicker.attachmentError'),
-                reason: translate('attachmentPicker.folderNotAllowedMessage'),
-            };
-        case CONST.FILE_VALIDATION_ERRORS.MAX_FILE_LIMIT_EXCEEDED:
-            return {
-                title: translate('attachmentPicker.someFilesCantBeUploaded'),
-                reason: translate('attachmentPicker.maxFileLimitExceeded'),
-            };
         case CONST.FILE_VALIDATION_ERRORS.FILE_CORRUPTED:
             return {
                 title: translate('attachmentPicker.attachmentError'),
@@ -774,21 +753,13 @@ const getFileValidationErrorText = (
                 reason: translate('attachmentPicker.imageDimensionsTooLarge'),
             };
         default:
-            return {
-                title: translate('attachmentPicker.attachmentError'),
-                reason: translate('attachmentPicker.errorWhileSelectingCorruptedAttachment'),
-            };
+            break;
     }
-};
 
-const getConfirmModalPrompt = (translate: LocalizedTranslate, attachmentInvalidReason: TranslationPaths | undefined) => {
-    if (!attachmentInvalidReason) {
-        return '';
-    }
-    if (attachmentInvalidReason === 'attachmentPicker.sizeExceededWithLimit') {
-        return translate(attachmentInvalidReason, CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE / (1024 * 1024));
-    }
-    return translate(attachmentInvalidReason);
+    return {
+        title: translate('attachmentPicker.attachmentError'),
+        reason: translate('attachmentPicker.errorWhileSelectingCorruptedAttachment'),
+    };
 };
 
 const MAX_CANVAS_SIZE = 4096;
@@ -902,16 +873,13 @@ export {
     resizeImageIfNeeded,
     createFile,
     validateReceipt,
-    validateAttachment,
     normalizeFileObject,
     isValidReceiptExtension,
     getFileValidationErrorText,
     hasHeicOrHeifExtension,
-    getConfirmModalPrompt,
     canvasFallback,
     getFilesFromClipboardEvent,
     cleanFileObject,
     cleanFileObjectName,
 };
-
-export type {ValidateAttachmentOptions};
+export type {FileValidationError};
diff --git a/src/libs/validateAttachmentFile.ts b/src/libs/validateAttachmentFile.ts
new file mode 100644
index 000000000000..f46fab1eb982
--- /dev/null
+++ b/src/libs/validateAttachmentFile.ts
@@ -0,0 +1,91 @@
+import {Str} from 'expensify-common';
+import type {ValueOf} from 'type-fest';
+import CONST from '@src/CONST';
+import type {FileObject} from '@src/types/utils/Attachment';
+import {cleanFileName, hasHeicOrHeifExtension, isValidReceiptExtension, normalizeFileObject, validateImageForCorruption} from './fileDownload/FileUtils';
+
+type ValidateAttachmentValidResult = {
+    isValid: true;
+    file: FileObject;
+};
+
+type ValidateAttachmentInvalidResult = {
+    isValid: false;
+    error: ValueOf<typeof CONST.FILE_VALIDATION_ERRORS>;
+};
+
+type ValidateAttachmentResult = ValidateAttachmentValidResult | ValidateAttachmentInvalidResult;
+
+async function validateAttachmentFile(file: FileObject, item?: DataTransferItem, isValidatingReceipts = false): Promise<ValidateAttachmentResult> {
+    if (!file.name || file.size == null) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.FILE_INVALID};
+    }
+
+    if (isValidatingReceipts && !isValidReceiptExtension(file)) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE};
+    }
+
+    if (hasHeicOrHeifExtension(file)) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.HEIC_OR_HEIF_IMAGE};
+    }
+
+    const isImage = Str.isImage(file.name);
+    const maxFileSize = isValidatingReceipts ? CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE : CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE;
+    if (!isImage && !hasHeicOrHeifExtension(file) && file.size > maxFileSize) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE};
+    }
+
+    if (isValidatingReceipts && file.size < CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.FILE_TOO_SMALL};
+    }
+
+    let fileObject = file;
+    const fileConverted = file.getAsFile?.();
+    if (fileConverted) {
+        fileObject = fileConverted;
+    }
+
+    if (!fileObject) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.FILE_INVALID};
+    }
+
+    if (isDataTransferItemDirectory(item)) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.FOLDER_NOT_ALLOWED};
+    }
+
+    const normalizedFile = await normalizeFileObject(fileObject);
+    try {
+        await validateImageForCorruption(normalizedFile);
+    } catch (error) {
+        return {isValid: false, error: CONST.FILE_VALIDATION_ERRORS.FILE_CORRUPTED};
+    }
+
+    if (normalizedFile instanceof File) {
+        /**
+         * Cleaning file name, done here so that it covers all cases:
+         * upload, drag and drop, copy-paste
+         */
+        let updatedFile = normalizedFile;
+        const cleanName = cleanFileName(updatedFile.name);
+        if (updatedFile.name !== cleanName) {
+            updatedFile = new File([updatedFile], cleanName, {type: updatedFile.type});
+        }
+        const inputSource = URL.createObjectURL(updatedFile);
+        updatedFile.uri = inputSource;
+
+        return {isValid: true, file: updatedFile};
+    }
+
+    return {isValid: true, file: normalizedFile};
+}
+
+function isDataTransferItemDirectory(item: DataTransferItem | undefined) {
+    if (item && item.kind === 'file' && 'webkitGetAsEntry' in item && item.webkitGetAsEntry()?.isDirectory) {
+        return true;
+    }
+
+    return false;
+}
+
+export default validateAttachmentFile;
+export type {ValidateAttachmentResult, ValidateAttachmentValidResult, ValidateAttachmentInvalidResult};
diff --git a/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx b/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx
index 430ee6f7eccb..3c5d9a94e4ec 100644
--- a/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx
+++ b/src/pages/iou/request/step/IOURequestStepOdometerImage/index.tsx
@@ -94,9 +94,6 @@ function IOURequestStepOdometerImage({
     };
 
     const {validateFiles, ErrorModal} = useFilesValidation((files: FileObject[]) => {
-        if (files.length === 0) {
-            return;
-        }
         const file = files.at(0);
         if (!file) {
             return;
diff --git a/src/pages/media/AttachmentModalScreen/routes/report/ReportAddAttachmentModalContent/index.tsx b/src/pages/media/AttachmentModalScreen/routes/report/ReportAddAttachmentModalContent/index.tsx
index 7e6feeb49063..31606deb2f2e 100644
--- a/src/pages/media/AttachmentModalScreen/routes/report/ReportAddAttachmentModalContent/index.tsx
+++ b/src/pages/media/AttachmentModalScreen/routes/report/ReportAddAttachmentModalContent/index.tsx
@@ -4,11 +4,10 @@ import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import useReportIsArchived from '@hooks/useReportIsArchived';
 import {openReport} from '@libs/actions/Report';
-import {validateAttachmentFile} from '@libs/AttachmentUtils';
-import type {AttachmentValidationResult} from '@libs/AttachmentUtils';
 import {getValidatedImageSource} from '@libs/AvatarUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import {canUserPerformWriteAction, isReportNotFound} from '@libs/ReportUtils';
+import validateAttachmentFile from '@libs/validateAttachmentFile';
 import type {AttachmentModalBaseContentProps} from '@pages/media/AttachmentModalScreen/AttachmentModalBaseContent/types';
 import AttachmentModalContainer from '@pages/media/AttachmentModalScreen/AttachmentModalContainer';
 import useDownloadAttachment from '@pages/media/AttachmentModalScreen/routes/hooks/useDownloadAttachment';
@@ -84,39 +83,27 @@ function ReportAddAttachmentModalContent({route, navigation}: AttachmentModalScr
 
     const [validFiles, setValidFiles] = useState<FileObject | FileObject[] | undefined>(fileParam);
     useEffect(() => {
-        if (!fileParam) {
-            return;
-        }
-
-        function updateState(result: AttachmentValidationResult | AttachmentValidationResult[]) {
-            if (Array.isArray(result)) {
-                const validResults = result.filter((r) => r.isValid);
-                if (validResults.length === 0) {
-                    return;
-                }
-
-                const validatedFiles = validResults.map((r) => r.file);
-                const firstValidSource = validResults.at(0)?.source;
-
-                setSource(firstValidSource);
-                setValidFiles(validatedFiles);
+        async function validateFiles() {
+            if (!fileParam) {
                 return;
             }
 
-            if (!result.isValid) {
+            const files = Array.isArray(fileParam) ? fileParam : [fileParam];
+            const results = await Promise.all(files.map(async (file) => validateAttachmentFile(file)));
+
+            const validResults = results.filter((r) => r.isValid);
+            if (validResults.length === 0) {
                 return;
             }
 
-            setSource(result.source);
-            setValidFiles(result.file);
-        }
+            const validatedFiles = validResults.map((r) => r.file);
+            const firstValidSource = validResults.at(0)?.file.uri;
 
-        if (Array.isArray(fileParam)) {
-            Promise.all(fileParam.map((f) => validateAttachmentFile(f))).then(updateState);
-            return;
+            setSource(firstValidSource);
+            setValidFiles(validatedFiles);
         }
 
-        validateAttachmentFile(fileParam).then(updateState);
+        validateFiles();
     }, [fileParam]);
 
     const modalType = useReportAttachmentModalType(source, validFiles);
diff --git a/tests/unit/FileUtilsTest.ts b/tests/unit/FileUtilsTest.ts
index fd583d42c73f..1859b8fae032 100644
--- a/tests/unit/FileUtilsTest.ts
+++ b/tests/unit/FileUtilsTest.ts
@@ -9,18 +9,12 @@ import {
     getFileValidationErrorText,
     getImageDimensionsAfterResize,
     splitExtensionFromFileName,
-    validateAttachment,
 } from '@libs/fileDownload/FileUtils';
 import CONST from '@src/CONST';
 
 jest.useFakeTimers();
 jest.mock('react-native-image-size');
 
-const createMockFile = (name: string, size: number) => ({
-    name,
-    size,
-});
-
 const createFileNameFromLength = ({length, extension}: {length: number; extension?: string | undefined}): string => `${'a'.repeat(length)}${extension ? `.${extension}` : ''}`;
 
 describe('FileUtils', () => {
@@ -104,56 +98,6 @@ describe('FileUtils', () => {
         });
     });
 
-    describe('validateAttachment', () => {
-        it('should not return FILE_TOO_SMALL when validating small attachment', () => {
-            const file = createMockFile('file.csv', CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE - 1);
-            const error = validateAttachment(file, {isValidatingMultipleFiles: false, isValidatingReceipts: false});
-            expect(error).not.toBe(CONST.FILE_VALIDATION_ERRORS.FILE_TOO_SMALL);
-        });
-
-        it('should return FILE_TOO_SMALL when validating small receipt', () => {
-            const file = createMockFile('receipt.jpg', CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE - 1);
-            const error = validateAttachment(file, {isValidatingMultipleFiles: false, isValidatingReceipts: true});
-            expect(error).toBe(CONST.FILE_VALIDATION_ERRORS.FILE_TOO_SMALL);
-        });
-
-        it('should return FILE_TOO_LARGE for large non-image file', () => {
-            const file = createMockFile('file.pdf', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE + 1);
-            const error = validateAttachment(file);
-            expect(error).toBe(CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE);
-        });
-
-        it('should return FILE_TOO_LARGE_MULTIPLE when checking multiple files', () => {
-            const file = createMockFile('file.pdf', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE + 1);
-            const error = validateAttachment(file, {isValidatingMultipleFiles: true, isValidatingReceipts: false});
-            expect(error).toBe(CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE_MULTIPLE);
-        });
-
-        it('should return WRONG_FILE_TYPE for invalid receipt extension', () => {
-            const file = createMockFile('receipt.exe', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
-            const error = validateAttachment(file, {isValidatingMultipleFiles: false, isValidatingReceipts: true});
-            expect(error).toBe(CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE);
-        });
-
-        it('should prioritize WRONG_FILE_TYPE over FILE_TOO_LARGE for receipts', () => {
-            const file = createMockFile('receipt.exe', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE + 10);
-            const error = validateAttachment(file, {isValidatingMultipleFiles: false, isValidatingReceipts: true});
-            expect(error).toBe(CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE);
-        });
-
-        it('should return WRONG_FILE_TYPE_MULTIPLE when checking multiple invalid receipt files', () => {
-            const file = createMockFile('receipt.exe', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE + 10);
-            const error = validateAttachment(file, {isValidatingMultipleFiles: true, isValidatingReceipts: true});
-            expect(error).toBe(CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE_MULTIPLE);
-        });
-
-        it('should return empty string for valid image receipt', () => {
-            const file = createMockFile('receipt.jpg', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
-            const error = validateAttachment(file, {isValidatingMultipleFiles: false, isValidatingReceipts: true});
-            expect(error).toBe('');
-        });
-    });
-
     describe('canvasFallback', () => {
         const mockCreateImageBitmap = jest.fn();
         const mockCanvas = {
@@ -521,7 +465,7 @@ describe('FileUtils', () => {
         const mockTranslate = ((path: string) => path) as LocaleContextProps['translate'];
 
         it('should return correct error text for IMAGE_DIMENSIONS_TOO_LARGE', () => {
-            const result = getFileValidationErrorText(mockTranslate, CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE);
+            const result = getFileValidationErrorText(mockTranslate, {error: CONST.FILE_VALIDATION_ERRORS.IMAGE_DIMENSIONS_TOO_LARGE});
 
             expect(result.title).toBe('attachmentPicker.attachmentError');
             expect(result.reason).toBe('attachmentPicker.imageDimensionsTooLarge');
diff --git a/tests/unit/ValidateAttachmentFileTest.ts b/tests/unit/ValidateAttachmentFileTest.ts
new file mode 100644
index 000000000000..ce3f393cae4f
--- /dev/null
+++ b/tests/unit/ValidateAttachmentFileTest.ts
@@ -0,0 +1,328 @@
+import validateAttachmentFile from '@libs/validateAttachmentFile';
+import type {FileObject} from '@src/types/utils/Attachment';
+import CONST from '../../src/CONST';
+import * as FileUtils from '../../src/libs/fileDownload/FileUtils';
+
+// Mock only normalizeFileObject and validateImageForCorruption; keep real hasHeicOrHeifExtension and isValidReceiptExtension
+jest.mock('@src/libs/fileDownload/FileUtils', () => {
+    const actual = jest.requireActual<typeof FileUtils>('@src/libs/fileDownload/FileUtils');
+    return {
+        ...actual,
+        normalizeFileObject: jest.fn(),
+        validateImageForCorruption: jest.fn(),
+    };
+});
+
+const mockFileUtils = FileUtils as jest.Mocked<typeof FileUtils>;
+
+const createMockFile = (name: string, size: number): FileObject => ({
+    name,
+    size,
+});
+
+describe('validateAttachmentFile', () => {
+    beforeEach(() => {
+        jest.clearAllMocks();
+        // Default: pass-through so async validation succeeds
+        mockFileUtils.normalizeFileObject.mockImplementation(async (file) => file);
+        mockFileUtils.validateImageForCorruption.mockResolvedValue(undefined);
+    });
+
+    describe('FILE_INVALID', () => {
+        it('returns invalid result with FILE_INVALID when file has no name', async () => {
+            const file = createMockFile('', 100);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FILE_INVALID);
+        });
+
+        it('returns invalid result with FILE_INVALID when file has undefined size', async () => {
+            const file: FileObject = {name: 'receipt.jpg', size: undefined};
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FILE_INVALID);
+        });
+
+        it('returns invalid result with FILE_INVALID when file has null size', async () => {
+            const file: FileObject = {name: 'receipt.jpg', size: null as unknown as number};
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FILE_INVALID);
+        });
+    });
+
+    describe('WRONG_FILE_TYPE', () => {
+        it('returns invalid result with WRONG_FILE_TYPE for invalid receipt extension when validating receipts', async () => {
+            const file = createMockFile('receipt.exe', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE);
+        });
+
+        it('returns invalid result with WRONG_FILE_TYPE (not FILE_TOO_LARGE) when receipt has wrong type and is over size', async () => {
+            const file = createMockFile('receipt.exe', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE + 10);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.WRONG_FILE_TYPE);
+        });
+
+        it('returns valid result when not validating receipts, even for invalid receipt extension', async () => {
+            const file = createMockFile('file.exe', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, false);
+
+            expect(error.isValid).toBe(true);
+        });
+    });
+
+    describe('HEIC_OR_HEIF_IMAGE', () => {
+        it('returns invalid result with HEIC_OR_HEIF_IMAGE for .heic file', async () => {
+            const file = createMockFile('image.heic', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.HEIC_OR_HEIF_IMAGE);
+        });
+
+        it('returns invalid result with HEIC_OR_HEIF_IMAGE for .heif file', async () => {
+            const file = createMockFile('image.heif', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.HEIC_OR_HEIF_IMAGE);
+        });
+    });
+
+    describe('FILE_TOO_LARGE', () => {
+        it('returns invalid result with FILE_TOO_LARGE for non-image over MAX_SIZE (general attachment)', async () => {
+            const file = createMockFile('file.pdf', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE + 1);
+            const error = await validateAttachmentFile(file);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE);
+        });
+
+        it('returns invalid result with FILE_TOO_LARGE for non-image receipt over RECEIPT_MAX_SIZE', async () => {
+            const file = createMockFile('receipt.pdf', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE + 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FILE_TOO_LARGE);
+        });
+
+        it('returns valid result for image over RECEIPT_MAX_SIZE (images skip non-image size check)', async () => {
+            const file = createMockFile('receipt.jpg', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE + 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result when non-image is exactly at MAX_SIZE', async () => {
+            const file = createMockFile('file.pdf', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE);
+            const error = await validateAttachmentFile(file);
+
+            expect(error.isValid).toBe(true);
+        });
+    });
+
+    describe('FILE_TOO_SMALL', () => {
+        it('returns invalid result with FILE_TOO_SMALL for receipt below MIN_SIZE', async () => {
+            const file = createMockFile('receipt.jpg', CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FILE_TOO_SMALL);
+        });
+
+        it('returns valid result when not validating receipts, even for small file size', async () => {
+            const file = createMockFile('file.csv', CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE - 1);
+            const error = await validateAttachmentFile(file);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result when receipt is exactly at MIN_SIZE', async () => {
+            const file = createMockFile('receipt.jpg', CONST.API_ATTACHMENT_VALIDATIONS.MIN_SIZE);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+    });
+
+    describe('FOLDER_NOT_ALLOWED', () => {
+        it('returns invalid result with FOLDER_NOT_ALLOWED when DataTransferItem is a directory', async () => {
+            const mockItem = {
+                kind: 'file' as const,
+                webkitGetAsEntry: jest.fn(() => ({
+                    isDirectory: true,
+                })),
+            } as unknown as DataTransferItem;
+
+            const file = createMockFile('folder', 0);
+            const error = await validateAttachmentFile(file, mockItem);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FOLDER_NOT_ALLOWED);
+        });
+
+        it('returns valid result when DataTransferItem is not a directory', async () => {
+            const mockItem = {
+                kind: 'file' as const,
+                webkitGetAsEntry: jest.fn(() => ({
+                    isDirectory: false,
+                })),
+            } as unknown as DataTransferItem;
+
+            const file = createMockFile('file.pdf', 100);
+            const error = await validateAttachmentFile(file, mockItem);
+
+            expect(error.isValid).toBe(true);
+        });
+    });
+
+    describe('FILE_CORRUPTED', () => {
+        it('returns invalid result with FILE_CORRUPTED when validateImageForCorruption throws', async () => {
+            mockFileUtils.validateImageForCorruption.mockRejectedValue(new Error('Corrupted'));
+
+            const file = createMockFile('image.png', 1000);
+            const error = await validateAttachmentFile(file);
+
+            if (error.isValid) {
+                throw new Error('validateAttachmentFile should return an invalid result');
+            }
+
+            expect(error.error).toEqual(CONST.FILE_VALIDATION_ERRORS.FILE_CORRUPTED);
+        });
+    });
+
+    describe('success', () => {
+        it('returns valid result for valid image receipt at valid size', async () => {
+            const file = createMockFile('receipt.jpg', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid receipt at exact RECEIPT_MAX_SIZE', async () => {
+            const file = createMockFile('receipt.jpg', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid PDF receipt', async () => {
+            const file = createMockFile('receipt.pdf', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid PNG receipt', async () => {
+            const file = createMockFile('receipt.png', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid GIF receipt', async () => {
+            const file = createMockFile('receipt.gif', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid JPEG receipt', async () => {
+            const file = createMockFile('receipt.jpeg', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid non-image receipt (doc)', async () => {
+            const file = createMockFile('receipt.doc', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid non-image receipt (text)', async () => {
+            const file = createMockFile('receipt.text', CONST.API_ATTACHMENT_VALIDATIONS.RECEIPT_MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file, undefined, true);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid non-receipt attachment (CSV)', async () => {
+            const file = createMockFile('data.csv', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result for valid non-receipt image', async () => {
+            const file = createMockFile('image.png', CONST.API_ATTACHMENT_VALIDATIONS.MAX_SIZE - 1);
+            const error = await validateAttachmentFile(file);
+
+            expect(error.isValid).toBe(true);
+        });
+
+        it('returns valid result when file has getAsFile and uses converted file', async () => {
+            // In Node/Jest the react-native-url-polyfill throws for createObjectURL (no BlobModule).
+            // Mock it so the File path that assigns file.uri can run.
+            const createObjectURLSpy = jest.spyOn(URL, 'createObjectURL').mockReturnValue('blob:mock-url');
+            try {
+                const blob = new Blob(['content'], {type: 'text/plain'});
+                const convertedFile = new File([blob], 'file.txt', {type: 'text/plain'});
+                const file = {
+                    name: 'file.txt',
+                    size: 7,
+                    getAsFile: () => convertedFile,
+                } as unknown as FileObject;
+
+                const error = await validateAttachmentFile(file);
+
+                expect(error.isValid).toBe(true);
+                expect(mockFileUtils.normalizeFileObject).toHaveBeenCalledWith(convertedFile);
+            } finally {
+                createObjectURLSpy.mockRestore();
+            }
+        });
+    });
+});
