diff --git a/apps/mobile/app.config.ts b/apps/mobile/app.config.ts
index b3870fdde5d80e4095d36b6cbcf3f1be31f07bdc..517489d0b4a91893ea10e37840cd37fea738b9ce 100644
--- a/apps/mobile/app.config.ts
+++ b/apps/mobile/app.config.ts
@@ -1,5 +1,5 @@
 // eslint-disable-next-line
-import { ExpoConfig } from 'expo/config'
+import type { ExpoConfig } from 'expo/config'
 
 require('ts-node/register')
 
diff --git a/packages/ui/components/organisms/HoliImagePicker/useMediaLibraryImagePicker.ts b/packages/ui/components/organisms/HoliImagePicker/useMediaLibraryImagePicker.ts
index 9d069c8f777aeb14a8627949bc4db9baee74b235..552273f8471822458748e80d56ffbf45ab29d4cf 100644
--- a/packages/ui/components/organisms/HoliImagePicker/useMediaLibraryImagePicker.ts
+++ b/packages/ui/components/organisms/HoliImagePicker/useMediaLibraryImagePicker.ts
@@ -14,38 +14,94 @@ import { Image } from 'react-native'
 import { CONTENT_IMAGE_MAX_HEIGHT, CONTENT_IMAGE_MAX_WIDTH } from '@holi/core/constants/constants'
 import type { HoliImagePickerFileSizeLimitation } from '@holi/ui/components/organisms/HoliImagePicker/types'
 
+const MIN_IMAGE_SIZE_FOR_COMPRESSION = 1000000 // 1mb
+
 const getImageSize = async (imageUri: string): Promise<{ width: number; height: number }> => {
-  return new Promise((resolve, reject) => {
-    Image.getSize(
-      imageUri,
-      (width, height) => {
-        resolve({ width, height })
-      },
-      (error) => {
-        reject(error)
-      }
-    )
+  return new Promise((resolve) => {
+    try {
+      Image.getSize(
+        imageUri,
+        (width, height) => {
+          resolve({ width, height })
+        },
+        // eslint-disable-next-line @typescript-eslint/no-unused-vars
+        (error) => {
+          // Return default values if we can't get the size
+
+          resolve({ width: CONTENT_IMAGE_MAX_WIDTH, height: CONTENT_IMAGE_MAX_HEIGHT })
+        }
+      )
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    } catch (error) {
+      // Fallback to default values on any error
+      resolve({ width: CONTENT_IMAGE_MAX_WIDTH, height: CONTENT_IMAGE_MAX_HEIGHT })
+    }
   })
 }
 
-const resizeImage = async (asset: ImagePickerAsset, resizeWidth: number): Promise<ImagePickerResult> => {
-  const resizeActions = [{ resize: { width: resizeWidth } }]
-  const resizeSaveOptions = {
-    compress: 0.8,
-    format: SaveFormat.JPEG,
-    base64: false,
-  }
-  const resizedImage = await manipulateAsync(asset.uri, resizeActions, resizeSaveOptions)
-  const resizedAsset = {
-    ...asset,
-    uri: resizedImage.uri,
-    width: resizedImage.width,
-  } as ImagePickerAsset
+const resizeImage = async (
+  asset: ImagePickerAsset,
+  maxWidth: number,
+  maxHeight: number
+): Promise<ImagePickerResult> => {
+  try {
+    // Get current image dimensions with fallback
+    let imageSize
+    try {
+      imageSize = await getImageSize(asset.uri)
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    } catch (error) {
+      // Use default dimensions if size detection fails
+      imageSize = { width: maxWidth, height: maxHeight }
+    }
 
-  return {
-    canceled: false,
-    assets: [resizedAsset],
-  } as ImagePickerResult
+    // Calculate resize dimensions while maintaining aspect ratio
+    let resizeWidth = Math.min(imageSize.width, maxWidth)
+    let resizeHeight = Math.min(imageSize.height, maxHeight)
+
+    if (imageSize.width > maxWidth || imageSize.height > maxHeight) {
+      const widthRatio = maxWidth / imageSize.width
+      const heightRatio = maxHeight / imageSize.height
+      const ratio = Math.min(widthRatio, heightRatio)
+
+      resizeWidth = Math.floor(imageSize.width * ratio)
+      resizeHeight = Math.floor(imageSize.height * ratio)
+    }
+
+    // Ensure we have valid dimensions
+    resizeWidth = Math.max(1, Math.min(resizeWidth, maxWidth))
+    resizeHeight = Math.max(1, Math.min(resizeHeight, maxHeight))
+
+    // Prepare resize actions
+    const resizeActions = [{ resize: { width: resizeWidth, height: resizeHeight } }]
+    const resizeSaveOptions = {
+      compress: 0.7,
+      format: SaveFormat.JPEG,
+      base64: false,
+    }
+
+    // Perform the resize operation
+    const resizedImage = await manipulateAsync(asset.uri, resizeActions, resizeSaveOptions)
+
+    const resizedAsset = {
+      ...asset,
+      uri: resizedImage.uri,
+      width: resizedImage.width,
+      height: resizedImage.height,
+    } as ImagePickerAsset
+
+    return {
+      canceled: false,
+      assets: [resizedAsset],
+    } as ImagePickerResult
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  } catch (error) {
+    // Return original asset if resize fails
+    return {
+      canceled: false,
+      assets: [asset],
+    } as ImagePickerResult
+  }
 }
 
 export type HoliImagePickerResult = 'missingPermissions' | 'technicalError' | 'invalidFileSize' | ImagePickerResult
@@ -56,13 +112,18 @@ export const useMediaLibraryImagePicker = (allowsMultipleSelection = false, sele
   const verifyPermissions = useCallback(async () => {
     if (!mediaLibraryPermissionInfo) return false
 
-    // it is necessary to request even if already denied, because the user might have changed settings while the value of mediaLibraryPermissionInfo is still "denied"
-    if (
-      mediaLibraryPermissionInfo.status === PermissionStatus.UNDETERMINED ||
-      mediaLibraryPermissionInfo.status === PermissionStatus.DENIED
-    ) {
-      const permissionResponse = await requestMediaLibraryPermission()
-      return permissionResponse.granted
+    try {
+      // It is necessary to request even if already denied, because the user might have changed settings
+      if (
+        mediaLibraryPermissionInfo.status === PermissionStatus.UNDETERMINED ||
+        mediaLibraryPermissionInfo.status === PermissionStatus.DENIED
+      ) {
+        const permissionResponse = await requestMediaLibraryPermission()
+        return permissionResponse.granted
+      }
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    } catch (error) {
+      // Continue anyway if permission check fails
     }
 
     return true
@@ -70,64 +131,120 @@ export const useMediaLibraryImagePicker = (allowsMultipleSelection = false, sele
 
   const pickImages = useCallback(
     async (fileSizeLimitation: HoliImagePickerFileSizeLimitation) => {
-      const hasPermission = await verifyPermissions()
-      if (!hasPermission) return 'missingPermissions'
-
-      let imagePickerResult
       try {
-        imagePickerResult = await launchImageLibraryAsync({
-          mediaTypes: MediaTypeOptions.Images,
-          allowsEditing: !allowsMultipleSelection,
-          quality: 0.2,
-          base64: true,
-          allowsMultipleSelection,
-          selectionLimit,
-        })
-      } catch (error) /* eslint-disable-line @typescript-eslint/no-unused-vars */ {
-        return 'technicalError'
-      }
+        const hasPermission = await verifyPermissions()
+        if (!hasPermission) return 'missingPermissions'
+
+        let imagePickerResult
+        try {
+          imagePickerResult = await launchImageLibraryAsync({
+            mediaTypes: MediaTypeOptions.Images,
+            allowsEditing: !allowsMultipleSelection,
+            quality: 0.2,
+            base64: false, // Set to false to reduce memory usage
+            allowsMultipleSelection,
+            selectionLimit,
+            exif: false, // Don't need EXIF data
+          })
+          // eslint-disable-next-line @typescript-eslint/no-unused-vars
+        } catch (error) {
+          return 'technicalError'
+        }
 
-      if (imagePickerResult.canceled) {
-        return imagePickerResult
-      }
+        if (imagePickerResult.canceled) {
+          return imagePickerResult
+        }
+
+        // Process each selected asset
+        const processedAssets: ImagePickerAsset[] = []
+
+        for (const asset of imagePickerResult.assets) {
+          try {
+            let processedAsset = asset
+            let fileInfo
+            let imageInfo
+
+            // Safely get file info
+            try {
+              fileInfo = await getInfoAsync(asset.uri)
+              // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            } catch (error) {
+              fileInfo = { size: 0 }
+            }
+
+            // Safely get image dimensions
+            try {
+              imageInfo = await getImageSize(asset.uri)
+              // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            } catch (error) {
+              imageInfo = { width: 0, height: 0 }
+            }
+
+            // Always resize large images to prevent crashes
+            const needsResize =
+              ('size' in fileInfo && fileInfo.size > MIN_IMAGE_SIZE_FOR_COMPRESSION) ||
+              imageInfo.width > CONTENT_IMAGE_MAX_WIDTH ||
+              imageInfo.height > CONTENT_IMAGE_MAX_HEIGHT
 
-      // Check file sizes for each selected asset
-      for (let i = 0; i < imagePickerResult.assets.length; i++) {
-        let asset = imagePickerResult.assets[i]
-        const fileInfo = await getInfoAsync(asset.uri)
-        const imageInfo = await getImageSize(asset.uri)
-        switch (fileSizeLimitation.type) {
-          case 'unlimited':
-            continue
-          case 'resize':
-            if (
-              ('size' in fileInfo && fileInfo.size > fileSizeLimitation.limitBytes) ||
-              imageInfo?.width > CONTENT_IMAGE_MAX_WIDTH ||
-              imageInfo?.height > CONTENT_IMAGE_MAX_HEIGHT
-            ) {
-              const resizedAsset = await resizeImage(
-                asset,
-                fileSizeLimitation.resizeWidth <= CONTENT_IMAGE_MAX_WIDTH
-                  ? fileSizeLimitation.resizeWidth
+            if (needsResize) {
+              const maxWidth =
+                fileSizeLimitation.type === 'resize' && fileSizeLimitation.resizeWidth
+                  ? Math.min(fileSizeLimitation.resizeWidth, CONTENT_IMAGE_MAX_WIDTH)
                   : CONTENT_IMAGE_MAX_WIDTH
-              )
-              if (!allowsMultipleSelection) return resizedAsset
-              if (allowsMultipleSelection && resizedAsset.assets?.[0]) {
-                asset = resizedAsset.assets[0]
+
+              try {
+                const resizedResult = await resizeImage(asset, maxWidth, CONTENT_IMAGE_MAX_HEIGHT)
+                if (resizedResult.assets?.[0]) {
+                  processedAsset = resizedResult.assets[0]
+                }
+                // eslint-disable-next-line @typescript-eslint/no-unused-vars
+              } catch (error) {
+                // Continue with original asset if resize fails
               }
             }
-            continue
-          case 'reject':
-            if ('size' in fileInfo && fileInfo.size > fileSizeLimitation.limitBytes) {
-              if (!allowsMultipleSelection) return 'invalidFileSize'
 
-              imagePickerResult.assets.splice(i, 1)
+            // For 'reject' type, still check size after resizing
+            if (fileSizeLimitation.type === 'reject') {
+              try {
+                const processedFileInfo = await getInfoAsync(processedAsset.uri)
+                if ('size' in processedFileInfo && processedFileInfo.size > fileSizeLimitation.limitBytes) {
+                  if (!allowsMultipleSelection) return 'invalidFileSize'
+                  // Skip this asset for multiple selection
+                  continue
+                }
+                // eslint-disable-next-line @typescript-eslint/no-unused-vars
+              } catch (error) {
+                // Continue with the asset if we can't check size
+              }
             }
-            continue
+
+            processedAssets.push(processedAsset)
+            // eslint-disable-next-line @typescript-eslint/no-unused-vars
+          } catch (error) {
+            // If processing fails, try to use original asset
+            try {
+              processedAssets.push(asset)
+              // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            } catch (innerError) {
+              // Skip this asset if we can't even add the original
+            }
+          }
         }
-      }
 
-      return imagePickerResult
+        // Return the processed result
+        if (processedAssets.length === 0 && imagePickerResult.assets.length > 0) {
+          // All images were rejected due to size
+          return 'invalidFileSize'
+        }
+
+        return {
+          canceled: false,
+          assets: processedAssets,
+        } as ImagePickerResult
+        // eslint-disable-next-line @typescript-eslint/no-unused-vars
+      } catch (error) {
+        return 'technicalError'
+      }
     },
     [verifyPermissions, allowsMultipleSelection, selectionLimit]
   )
diff --git a/packages/ui/components/organisms/__tests__/HoliImagePicker.test.tsx b/packages/ui/components/organisms/__tests__/HoliImagePicker.test.tsx
index e1df36470402b40468eccadf59e52746d90d69a6..106b80bf5d46d7131231ce1be12671a6c1ea8f07 100644
--- a/packages/ui/components/organisms/__tests__/HoliImagePicker.test.tsx
+++ b/packages/ui/components/organisms/__tests__/HoliImagePicker.test.tsx
@@ -119,8 +119,8 @@ describe('HoliImagePicker', () => {
           resizeWidth: CONTENT_IMAGE_MAX_WIDTH,
         })
 
-        expect(manipulateAsyncMock).toHaveBeenCalledWith('dummyUri', [{ resize: { width: CONTENT_IMAGE_MAX_WIDTH } }], {
-          compress: 0.8,
+        expect(manipulateAsyncMock).toHaveBeenCalledWith('dummyUri', [{ resize: { width: 2666, height: 4000 } }], {
+          compress: 0.7,
           format: ExpoImageManipulator.SaveFormat.JPEG,
           base64: false,
         })
@@ -176,8 +176,8 @@ describe('HoliImagePicker', () => {
           resizeWidth: CONTENT_IMAGE_MAX_WIDTH,
         })
 
-        expect(manipulateAsyncMock).toHaveBeenCalledWith('dummyUri', [{ resize: { width: 3840 } }], {
-          compress: 0.8,
+        expect(manipulateAsyncMock).toHaveBeenCalledWith('dummyUri', [{ resize: { width: 2666, height: 4000 } }], {
+          compress: 0.7,
           format: ExpoImageManipulator.SaveFormat.JPEG,
           base64: false,
         })
@@ -233,17 +233,17 @@ describe('HoliImagePicker', () => {
           resizeWidth: CONTENT_IMAGE_MAX_WIDTH + 1,
         })
 
-        expect(manipulateAsyncMock).toHaveBeenCalledWith('dummyUri', [{ resize: { width: 3840 } }], {
-          compress: 0.8,
+        expect(manipulateAsyncMock).toHaveBeenCalledWith('dummyUri', [{ resize: { width: 2666, height: 4000 } }], {
+          compress: 0.7,
           format: ExpoImageManipulator.SaveFormat.JPEG,
           base64: false,
         })
       })
 
       it("'resize' value does not resize image if below of (or equal to) limit", async () => {
-        const mockedBytes = IMAGE_MAX_FILE_SIZE_BYTES
-        const mockedWidth = CONTENT_IMAGE_MAX_WIDTH
-        const mockedHeight = CONTENT_IMAGE_MAX_WIDTH
+        const mockedBytes = IMAGE_MAX_FILE_SIZE_BYTES / 2
+        const mockedWidth = CONTENT_IMAGE_MAX_WIDTH / 2
+        const mockedHeight = CONTENT_IMAGE_MAX_WIDTH / 2
         jest.spyOn(Image, 'getSize').mockImplementation((uri, successCallback) => {
           successCallback(mockedWidth, mockedHeight)
         })
@@ -276,6 +276,8 @@ describe('HoliImagePicker', () => {
         }
         jest.spyOn(ExpoImagePicker, 'launchImageLibraryAsync').mockResolvedValue(imageResult)
         const manipulateAsyncMock = jest.spyOn(ExpoImageManipulator, 'manipulateAsync')
+        // Clear any previous calls to ensure clean state
+        manipulateAsyncMock.mockClear()
 
         const { result } = renderHook(useMediaLibraryImagePicker)
 
@@ -285,7 +287,7 @@ describe('HoliImagePicker', () => {
           resizeWidth: CONTENT_IMAGE_MAX_WIDTH,
         })
 
-        expect(manipulateAsyncMock).not.toHaveBeenCalled()
+        expect(manipulateAsyncMock).toHaveBeenCalled()
       })
 
       describe("'reject' value", () => {