Description
Every post that contains at least one image is silently corrupted the moment it is read back from the database. The root cause is that TypeORM's simple-array column type stores arrays by naively joining values with a comma (value.join(",")) and reads them back by splitting on comma (value.split(",")) — with no escaping whatsoever.
Base64 data URLs produced by FileReader.readAsDataURL() always contain a literal comma in their MIME prefix (e.g. data:image/png;base64,iVBORw0KGgo...). This comma is indistinguishable from simple-array's delimiter, so the stored string is always parsed incorrectly on read.
Single-image post
Stored fine (nothing to join), but .split(",") still fires unconditionally on read, breaking data:image/png;base64,AAAA... into two entries:
data:image/png;base64 — a truncated, invalid data URL with no payload
AAAA... — a bare base64 string with no data: prefix, which the browser treats as a relative URL, not an image
Multi-image post
The join-separator comma and each image's own internal comma become completely indistinguishable. Images interleave and split at wrong boundaries, corrupting the entire set.
This is very likely the root cause of the "flying stars / meteor shower" rendering artefacts previously reported — corrupted/partial image decodes rather than someone else's real photos.
Steps to reproduce
- Create a post and attach one or more images via the upload flow (
post/+page.svelte)
- Save the post
- Navigate to the post grid / open the post detail
- Observe that images render as broken fragments, garbled pieces, or show browser image-load errors
Expected behavior
Uploaded images should be stored and retrieved without corruption. The full, valid base64 data URL should be recovered exactly as it was before storage, and images should render correctly in the post grid and post modal.
Current workaround
A frontend bandage — pairAndJoinChunks — exists in both Post.svelte (lines 32–55) and PostModal.svelte (line 45). It takes the corrupted flat array and re-pairs elements two-at-a-time, rejoining [prefix, payload] back into prefix,payload. This partially recovers single-image posts but remains brittle for multi-image posts where additional internal commas cause further mis-splits.
Proposed fix
Switch the column encoding from simple-array to simple-json (uses JSON.stringify / JSON.parse), which correctly escapes all internal characters including commas.
Both simple-array and simple-json compile down to a plain Postgres text column (confirmed by the original migration SQL — "images" text), so no schema migration is required.
Impact on existing data
Existing rows were stored with the old comma-joined format. Reading them with a JSON.parse decoder will throw a parse error rather than silently returning garbage. Old corrupted rows should be audited and either cleaned up or null-ed out before the fix is deployed, as the original image data cannot be reliably reconstructed from the corrupted fragments.
Steps
- Change the
images column decorator from simple-array to simple-json in the relevant TypeORM entity
- Remove the
pairAndJoinChunks workaround from Post.svelte and PostModal.svelte
- Handle/migrate (or purge) existing corrupted rows to prevent JSON parse errors at runtime
- Verify with a new post containing multiple images that all images are stored and displayed correctly
Supporting Media
N/A
Desktop
- Device: N/A (server-side / DB layer bug)
- OS: N/A
- Browser: N/A
- Version: N/A
Additional Context
- Corruption affects every single post with at least one image — no posts are safe under the current encoding
- If real users are onboarded before this is fixed, their uploaded images will be permanently unrecoverable
- The fix is low-risk (no SQL schema change needed) but requires careful handling of already-corrupted rows in the DB
Description
Every post that contains at least one image is silently corrupted the moment it is read back from the database. The root cause is that TypeORM's
simple-arraycolumn type stores arrays by naively joining values with a comma (value.join(",")) and reads them back by splitting on comma (value.split(",")) — with no escaping whatsoever.Base64 data URLs produced by
FileReader.readAsDataURL()always contain a literal comma in their MIME prefix (e.g.data:image/png;base64,iVBORw0KGgo...). This comma is indistinguishable fromsimple-array's delimiter, so the stored string is always parsed incorrectly on read.Single-image post
Stored fine (nothing to join), but
.split(",")still fires unconditionally on read, breakingdata:image/png;base64,AAAA...into two entries:data:image/png;base64— a truncated, invalid data URL with no payloadAAAA...— a bare base64 string with nodata:prefix, which the browser treats as a relative URL, not an imageMulti-image post
The join-separator comma and each image's own internal comma become completely indistinguishable. Images interleave and split at wrong boundaries, corrupting the entire set.
This is very likely the root cause of the "flying stars / meteor shower" rendering artefacts previously reported — corrupted/partial image decodes rather than someone else's real photos.
Steps to reproduce
post/+page.svelte)Expected behavior
Uploaded images should be stored and retrieved without corruption. The full, valid base64 data URL should be recovered exactly as it was before storage, and images should render correctly in the post grid and post modal.
Current workaround
A frontend bandage —
pairAndJoinChunks— exists in bothPost.svelte(lines 32–55) andPostModal.svelte(line 45). It takes the corrupted flat array and re-pairs elements two-at-a-time, rejoining[prefix, payload]back intoprefix,payload. This partially recovers single-image posts but remains brittle for multi-image posts where additional internal commas cause further mis-splits.Proposed fix
Switch the column encoding from
simple-arraytosimple-json(usesJSON.stringify/JSON.parse), which correctly escapes all internal characters including commas.Both
simple-arrayandsimple-jsoncompile down to a plain Postgrestextcolumn (confirmed by the original migration SQL —"images" text), so no schema migration is required.Impact on existing data
Existing rows were stored with the old comma-joined format. Reading them with a
JSON.parsedecoder will throw a parse error rather than silently returning garbage. Old corrupted rows should be audited and either cleaned up or null-ed out before the fix is deployed, as the original image data cannot be reliably reconstructed from the corrupted fragments.Steps
imagescolumn decorator fromsimple-arraytosimple-jsonin the relevant TypeORM entitypairAndJoinChunksworkaround fromPost.svelteandPostModal.svelteSupporting Media
N/A
Desktop
Additional Context