Symptom
On a page that is not yet service-worker-controlled (first visit while the SW is still installing, or a reload before activation), MapLibre basemap tiles can fail with net::ERR_CONTENT_DECODING_FAILED on data/basemap.pmtiles Range requests. The map shows the error banner; harbor lists and the rest of the UI work.
Root cause (verified live 2026-07-16)
GitHub Pages (Fastly) misbehaves for Range requests when its edge cache holds the gzip variant of the object: it slices the raw file bytes (content-range totals match the raw size) but stamps content-encoding: gzip on the 206. The browser then tries to gunzip plain bytes and fails.
HTTP/2 206
content-encoding: gzip <-- lie
content-range: bytes 0-16383/27192908 <-- raw-byte slicing
content-length: 16384
vary: Accept-Encoding
x-cache: HIT
- Cold edge (
x-cache: MISS pass-through): ranges are valid → first loads often work.
- Warm edge: broken. Ironically, the SW's own full-body precache GET is what warms the edge — so a reload during install is the most likely broken case.
- Once the SW controls the page,
.pmtiles ranges are sliced from the precache by createPartialResponse and are always correct (verified: 206, exact byte counts, zero console errors). The copied content-encoding header on the synthetic response is harmless — Chrome does not content-decode SW-synthesized responses.
So the app self-heals after first install; only the uncontrolled window is exposed.
Candidate mitigations
- One-shot recovery on first
controllerchange: if MapLibre logged tile errors while uncontrolled, reload the page (or re-add the pmtiles source) once the SW claims. Cheap, targeted.
- Shrink the uncontrolled window by making install fast (see companion issue on precache size).
- Longer term: host
basemap.pmtiles on an origin with sane Range+encoding behavior. Protomaps docs explicitly discourage GitHub Pages for PMTiles.
Evidence
Live verification session 2026-07-16: 28 console errors (ERR_CONTENT_DECODING_FAILED + MapLibre) on a reload mid-install; third load under SW control: 0 errors, map renders.
Symptom
On a page that is not yet service-worker-controlled (first visit while the SW is still installing, or a reload before activation), MapLibre basemap tiles can fail with
net::ERR_CONTENT_DECODING_FAILEDondata/basemap.pmtilesRange requests. The map shows the error banner; harbor lists and the rest of the UI work.Root cause (verified live 2026-07-16)
GitHub Pages (Fastly) misbehaves for
Rangerequests when its edge cache holds the gzip variant of the object: it slices the raw file bytes (content-range totals match the raw size) but stampscontent-encoding: gzipon the 206. The browser then tries to gunzip plain bytes and fails.x-cache: MISSpass-through): ranges are valid → first loads often work..pmtilesranges are sliced from the precache bycreatePartialResponseand are always correct (verified: 206, exact byte counts, zero console errors). The copiedcontent-encodingheader on the synthetic response is harmless — Chrome does not content-decode SW-synthesized responses.So the app self-heals after first install; only the uncontrolled window is exposed.
Candidate mitigations
controllerchange: if MapLibre logged tile errors while uncontrolled, reload the page (or re-add the pmtiles source) once the SW claims. Cheap, targeted.basemap.pmtileson an origin with sane Range+encoding behavior. Protomaps docs explicitly discourage GitHub Pages for PMTiles.Evidence
Live verification session 2026-07-16: 28 console errors (
ERR_CONTENT_DECODING_FAILED+ MapLibre) on a reload mid-install; third load under SW control: 0 errors, map renders.