iOS: 48MP photos fail to upload (413) — JPEG conversion without downscaling

Open Beginner friendly
#1,749 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
ios, typescript
Domain
api, mobile-dev

Research direction

Start in sources/hooks/useImagePicker.ts at normalizePickedAssetForUpload and inspect how the converted asset is passed into the upload flow. Add bounded dimensions to the JPEG conversion, then reproduce the 48MP iOS upload and confirm the converted file stays under 10MB and no longer receives a 413 response.

Written by the indexing model from the issue text.

Description

Summary

On iOS, picked photos are converted to JPEG (q0.92) without any downscaling. 48MP photos from recent iPhones (6048×8064) end up over the 10MB server limit after conversion, and the upload is rejected with 413. 12MP photos and screenshots work fine.

Steps to reproduce

  1. iPhone 17 Pro Max, camera in 48MP mode
  2. Pick a 48MP HEIC photo (~6.3MB original) in a chat
  3. Send → fails with a generic "attachment too large" toast; server returns 413

Root cause

In sources/hooks/useImagePicker.ts, normalizePickedAssetForUpload runs:

await ImageManipulator.manipulateAsync(asset.uri, [], {
  compress: 0.92,
  format: ImageManipulator.SaveFormat.JPEG,
});

No maxWidth/maxHeight is passed, so the resolution is unchanged. HEIC→JPEG at 6048×8064 with q0.92 produces a file larger than the 10MB limit.

The client-side size guard checks the original asset.fileSize (6.3MB — passes), but the converted blob is what gets encrypted and uploaded. The server (attachmentRoutes.ts) enforces 10MB on the actual upload, so the request fails with 413 and the user only sees a generic error toast.

Evidence

Asset Original After conversion Result
48MP photo (HEIC) 6.3MB >10MB ❌ 413
12MP photo (HEIC) ~1.8MB 2.69MB
Screenshot (PNG) 6.38MB 0.62MB

The converted size is what dominates, not the original.

Suggested fix

Add downsampling in normalizePickedAssetForUpload:

await ImageManipulator.manipulateAsync(asset.uri, [], {
  compress: 0.92,
  format: ImageManipulator.SaveFormat.JPEG,
  maxWidth: 3072,
  maxHeight: 3072,
});

A 48MP photo then converts to ~2–4MB, well within the limit, and model input size shrinks for all photos.

Alternative considered — skipping conversion entirely when the original is already ≤10MB — does not work end-to-end: HEIC is not an accepted input format for the model API, and the CLI (verified on 1.2.2) performs no HEIC transcoding before handing attachments to the model. So the JPEG conversion itself is still needed; only the missing downscale is the bug.

Environment

  • happy iOS app (Expo production build, published 2026-08-26)
  • iPhone 17 Pro Max, iOS 26
Dominant language
TypeScript
Stars
23.8k
Forks
2k
Avg merge
2d 16h
Merged PRs (30d)
13

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from slopus/happy

All issues in slopus/happy

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.