Skip to content

A picked profile photo is frozen into memory at selection time (v7.206.2) - #1256

Merged
wintermeyer merged 1 commit into
mainfrom
freeze-picked-photo-1227
Jul 31, 2026
Merged

A picked profile photo is frozen into memory at selection time (v7.206.2)#1256
wintermeyer merged 1 commit into
mainfrom
freeze-picked-photo-1227

Conversation

@wintermeyer

Copy link
Copy Markdown
Owner

Round 2 of #1227 (do not auto-close; the member confirms first).

What the capture showed after v7.206.1. The member's photo upload still 400ed: multipart submits with Content-Length: 0, from Safari and from the DuckDuckGo browser for macOS — which is WKWebView, i.e. the same system WebKit (605.1.15/26.5.2). Minutes earlier another member's iPhone on the identical WebKit version saved fine through the new urlencoded fallback. So the engine version is innocent; the multipart file stream on his Mac is what dies. Both post-fix attempts were multipart, meaning a file was selected — consistent with his comment ("Profilbild-Upload lässt sich nicht speichern").

The mechanism this targets. WebKit streams a picked file from disk only at send time. A photo picked from the Photos media library in the file dialog is a temporary export, and by the time the member has been through the crop dialog and the rest of the form it can be gone — the body stream aborts and the browser sends zero bytes. That explains a deterministic failure on his machine across both WebKit browsers while Chrome users upload fine.

The fix. image_crop.js now freezes the picked file at selection time — reads the bytes (they are provably readable then; the crop dialog reads them too) into an in-memory File and swaps it into the input via DataTransfer. An in-memory file is serialized from RAM and cannot vanish before send. Identity-guarded against a quick re-pick, capped at 32 MB, and a failed read leaves the plain upload in place exactly as before. No server changes.

Verified in a real browser against a dev server: pick → freeze (data-frozen-pick set, new File object, same bytes) → crop dialog → real submit → the server logs a genuine %Plug.Upload{} with the crop fractions and the avatar stores. mix precommit green (6,240 tests).

An AI agent wrote this text in my name, unreviewed by me. The work behind it is mine; I only delegated the writing.

https://claude.ai/code/session_014ksBm1P9qsazixAHFeHwMc

…6.2)

Issue #1227, round 2: with the fileless fallback live, the member's
photo upload still 400ed - the capture shows multipart submits with
Content-Length: 0 from Safari AND the DuckDuckGo browser for macOS,
which share the same system WebKit. Meanwhile another member's iPhone
on the identical WebKit version saved fine via the urlencoded fallback,
so the engine version is not the culprit; the multipart file stream is.

WebKit streams a picked file from disk only when the form is sent, and
a photo picked from the Photos media library is a temporary export that
can vanish while the member sits in the crop dialog and the rest of the
form - the body stream then aborts and the browser submits zero bytes.
So the crop enhancement now copies the picked file into an in-memory
File at selection time, when the bytes are provably readable (the crop
dialog reads them too), and swaps it into the input via DataTransfer.
An in-memory File is serialized from RAM and cannot vanish before send.
Guarded by object identity against a quick re-pick, capped at 32 MB,
and a failed read leaves the plain upload in place as before.

No server changes. Smoke-tested end to end in a real browser: the
frozen file arrives as a %Plug.Upload{} through the unchanged multipart
path, crop fractions intact, and the avatar stores.

An AI agent wrote this text in my name, unreviewed by me. The work
behind it is mine; I only delegated the writing.

Claude-Session: https://claude.ai/code/session_014ksBm1P9qsazixAHFeHwMc
@wintermeyer
wintermeyer merged commit e273c57 into main Jul 31, 2026
1 check passed
@wintermeyer
wintermeyer deleted the freeze-picked-photo-1227 branch July 31, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant