-
v0.18.5 — iPhone uploads sent an empty body; the queue now owns the bytes
Some checks failedAudit / cargo audit (backend) (push) Failing after 9m1sAudit / npm audit (frontend) (push) Successful in 1m10sChecks / Backend — cargo test + clippy + fmt (push) Failing after 55sChecks / Keepsake viewer — builds, self-contained, committed artifact in sync (push) Has been cancelledChecks / E2E — typecheck + lint (push) Has been cancelledE2E / Playwright E2E (chromium + webkit) (push) Has been cancelledE2E / Cross-UA smoke matrix (push) Has been cancelledChecks / Frontend — vitest + svelte-check (push) Has been cancelledreleased this
2026-08-22 15:57:47 +00:00 | 2 commits to main since this releaseFrontend only. Backend unchanged since v0.18.0, no migration touched (31), so the
app image is re-tagged and v0.18.4 remains a valid rollback target.Measured at the proxy during the live event: iPhone POSTs arrived with
content_length=0 in 7-22 ms. Nothing reached the wire, so this was never a
transport problem. addToQueue stored the picked File itself, and WebKit persists
a File in IndexedDB as a REFERENCE to an OS file that iOS deletes once the picker
closes. The neutered File still reports .name and .size, send() does not throw,
and an empty body goes out.- Bytes are copied at pick time, chunked at 4 MB so a 500 MB video cannot take
the tab with it. - An unreadable blob is TERMINAL and never retried, detected by probing one
real byte because .size lies. This also stops items queued before the fix,
which still hold dead references, from retrying forever.
v0.18.4 made this worse rather than better: it reclassified the resulting 400 as
retryable, so every dead photo re-sent an empty body five times — 79 failed
requests against 1 success. That reclassification is still correct for a
genuinely truncated body; what was missing is that an empty body never gets that
far now.Downloads
- Bytes are copied at pick time, chunked at 4 MB so a 500 MB video cannot take