fix(upgrade): normalize image/jpg → image/jpeg for ID document upload (ENG-291)#607
Merged
Nodirbek75 merged 4 commits intomainfrom Apr 6, 2026
Merged
Conversation
closing #527 - Add zero-balance check to ConversionAmountError before amount-exceed check - Show red error immediately when fromWallet has no balance - Add emptyWallet i18n key to ConversionDetailsScreen for localization
… (ENG-291) Root cause: Android react-native-image-picker and Vision Camera return 'image/jpg' for some JPEG photos. The backend storage service only accepts ['image/jpeg', 'image/png', 'image/webp'] — 'image/jpg' causes InvalidFileTypeError → no upload URL generated → HTTP 400 on step 4. Changes: - app/utils/image-content-type.ts (new): shared normalizeContentType() and isValidContentType() utilities matching backend allowlist - app/hooks/useAccountUpgrade.tsx: normalize contentType before calling idDocumentUploadUrlGenerate and uploadFileToS3 - app/components/account-upgrade-flow/PhotoUploadField.tsx: - remove ALLOWED_FILE_TYPES (was out of sync with backend) - use normalizeContentType + isValidContentType from shared util - normalize before validating in both gallery and camera paths - fallback to 'image/jpeg' if camera blob.type is empty string - __tests__/hooks/use-account-upgrade-content-type.spec.ts (new): unit tests for normalizeContentType and isValidContentType Note: test infra (ttypescript + Node 25) has a pre-existing incompatibility — tests are written and will run when that's resolved. Fixes: ENG-291
accountNumber in GraphQL schema is now String (not Int). Remove Number() conversion — pass the string value directly. Paired with backend PR #319 (flash repo).
Nodirbek75
approved these changes
Apr 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root Cause (ENG-291)
HTTP 400 on account upgrade Step 4 (ID document upload) — Android v0.5.0.70.
The bug: Android's
react-native-image-pickerand Vision Camera return'image/jpg'for some JPEG photos. The backend storage service only accepts['image/jpeg', 'image/png', 'image/webp'].'image/jpg'is not in the backend allowlist →InvalidFileTypeError→ no upload URL generated → HTTP 400 on form submission.The 400 comes from the Flash backend — specifically the
idDocumentUploadUrlGeneratemutation, before any ERPNext interaction.Fix
New shared utility
app/utils/image-content-type.ts:normalizeContentType(type)— maps'image/jpg'→'image/jpeg', passes others throughisValidContentType(type)— checks against backend-compatible allowlistApplied in:
useAccountUpgrade.tsx— normalizes before calling upload URL mutation AND before the S3 PUTPhotoUploadField.tsx— normalizes in both gallery picker and camera paths; fallback to'image/jpeg'if camera blob.type is empty stringTesting
Unit tests written in
__tests__/hooks/use-account-upgrade-content-type.spec.ts. Test infra has a pre-existing ttypescript/Node25 incompatibility — tests will run when that's resolved. Manual verification: upload a photo taken with camera on Android and confirm step 4 completes successfully.Note for reviewers
The client-side
ALLOWED_FILE_TYPESarray inPhotoUploadField.tsxwas['image/jpeg', 'image/png', 'image/jpg']— it includedimage/jpgbut the backend didn't. This mismatch let through a type the backend would always reject. Now using the shared utility that matches backend behavior exactly.