Live HLS Stops Updating: Stale Playlist or Missing Segment?

Trace a stalled live HLS stream by comparing media-sequence snapshots, checking the newest segment, and separating CDN freshness from player recovery. Includes a reproducible HTTP fixture.

A live player can freeze while the page and top-level .m3u8 URL still return 200. That status alone says very little. The player may be receiving the same media playlist repeatedly, or it may see a new segment in an updated playlist but fail to download that segment. Those problems have different owners and different fixes.

This guide shows how to collect the smallest useful trace. Work only with streams you own or are authorized to inspect. Before sharing logs, remove signed query strings, cookies, tokens, viewer identifiers, and IP addresses.

Verification method — September 17, 2026: We ran a loopback HTTP fixture with Node.js 24.12.0. The first two responses for /live.m3u8 were identical: media sequence 100, listing segments 100–102. The third response advanced to sequence 101 and listed 101–103. Segment 102 returned 200, but the newly listed segment 103 intentionally returned 404. This reproduces two distinct HTTP-level observations: an unchanged playlist snapshot and an advanced playlist with an unavailable segment. The fixture serves text markers, not decodable video. We did not test actual playback, hls.js retry behavior, a live encoder, a CDN, or device reconnection. The reproduction script is kept in the project at scripts/test-live-hls-playlist-diagnosis.cjs.

Start with the media playlist, not the master URL

A multivariant or master playlist describes available variants. The live media playlist for the selected video, audio, or subtitle rendition lists the segments currently available. A successful request for the master does not prove the selected child playlist is fresh. Our master-versus-media playlist guide explains the distinction.

Open developer tools before reloading the player. Preserve the network log, then identify the selected media-playlist request, its final URL after redirects, and the segment requests that follow it. Filter for m3u8, ts, m4s, and your actual segment path. Use the M3U8 developer-tools guide if you need a request-tracing checklist.

Record at least two playlist responses, not merely two request statuses. For each response, note the #EXT-X-MEDIA-SEQUENCE, the first and last segment URI, #EXT-X-TARGETDURATION, whether #EXT-X-ENDLIST appears, response time, Date, Age, Cache-Control, ETag, and Last-Modified if present. Some of those headers may be absent; absence is itself worth recording, not inventing.

Read the two failure signatures

TraceWhat it establishesNext check
Playlist request fails with 4xx/5xx or a network errorThe client did not get a usable playlist responseOrigin, CDN, authorization, DNS, or connection
Several responses are byte-for-byte unchanged and show the same sequence and newest URIThe client has not discovered new media in those responsesPublication time, cache age, origin versus edge response, player reloads
Sequence and newest URI advance, but the new segment returns 404Playlist publication ran ahead of segment availability, or the segment path is wrongPackager order, origin object, CDN propagation, URL resolution
Segment returns 200 but playback remains frozenHTTP availability alone is not enoughResponse body, media timestamps, decoding, buffering, player errors
Playlist has #EXT-X-ENDLISTThe presentation says no more segments will be addedConfirm whether the event has actually ended

One unchanged response is not proof of a broken stream. A live playlist normally remains the same between publication events. Compare timestamps against the target duration and collect enough snapshots to see whether it advances. Likewise, a 200 segment response is not proof of decodable video; an HTML error page or an incompatible fragment may also be returned with a success status.

Understand the reload clock

RFC 8216 requires a client to reload an active live media playlist periodically. Under that specification, after a changed playlist it waits at least one target duration before the next attempt; after an unchanged playlist it waits one-half target duration. The server's publication rules are separate: a new version containing at least one new segment is made available within the timing bounds in the specification. Do not label a client “stuck” because it did not reload every second when the target duration is eight seconds.

These are protocol rules, not a promise that a third-party CDN or application will behave correctly. Low-Latency HLS may use blocking playlist reload and partial segments; apply the rules of the actual stream, not a generic fixed polling interval. Apple documents blocking reload separately for that mode.

For a conventional sliding live window, removed segment URIs leave in order and #EXT-X-MEDIA-SEQUENCE advances accordingly. A sequence jump after a long network outage may mean the player has fallen behind the available window, but sequence numbers alone do not tell you whether the decoder recovered. Check segment availability and playback time as separate evidence.

A small controlled trace

Our fixture returned these three consecutive playlist snapshots. It did not wait real target-duration intervals; it isolates response content, not timing compliance.

RequestHTTPMedia sequenceListed segmentsNewest segment status
First200100100, 101, 102102 → 200
Second200100100, 101, 102Unchanged response
Third200101101, 102, 103103 → 404

The second response shows that no new segment was advertised at that moment. The third proves that the playlist subsequently advanced, while the newly advertised object was not available at the tested URL. Neither observation, by itself, proves how a real video player would recover. The value of the trace is that an encoder/CDN owner can investigate a specific first failing request rather than being handed “live video froze.”

Separate origin, CDN, and player evidence

If an edge keeps returning an old playlist, compare the same playlist at the origin and at the CDN using equivalent authorization. Record the final URL and cache headers. A stale Age value can be a clue, but do not infer the entire cache policy from one header or assume every CDN exposes its state the same way. Avoid adding random query parameters as a permanent “fix”: signed URLs and cache keys may make that misleading or unsafe.

If the playlist advances but a segment is missing, request that exact URI as resolved relative to the media playlist URL. Check both status and response body. A segment advertised before it is retrievable can stall playback even though the playlist itself is fresh. RFC 8216 requires segments listed in a playlist to be immediately available. Inspect packager publication order and whether the origin and CDN expose the new object in time.

If the playlist and segment requests both succeed, move into the player. With hls.js, record LEVEL_LOADING, LEVEL_LOADED or LEVEL_UPDATED, FRAG_LOADING, FRAG_LOADED, and ERROR details where available, including whether an error is fatal. Its API distinguishes level-load failures from fragment-load failures. Do not assume an event fires identically on native Safari playback; use that browser's media diagnostics instead. For broader buffering symptoms, continue with our HLS buffering diagnosis.

What to test after a network reconnection

On each supported browser and real device, record whether the playlist request resumes, whether its sequence and newest URI advance, whether the next segment succeeds, and whether video time starts moving again. Test a brief offline period and one long enough for the sliding window to move past the old position. A desktop responsive viewport is not a substitute for a phone's radio handoff or background-media policy.

Do not automatically call video.play() on every network event and report success. Playback might be paused intentionally or blocked by browser policy; the stream might still be serving stale data. Keep a visible user-controlled Play path, and use the HLS autoplay diagnosis when the source loads but playback cannot start.

A useful incident report contains the last good media sequence, the first unchanged or failing response, the exact segment status, cache headers, browser and player versions, and whether playback resumed. That evidence distinguishes “the CDN served yesterday's window” from “the player could not decode today's segment.”

References

Follow the media playlist and the first newly advertised segment in order. When the evidence stops changing, you know where to investigate next; you do not need to guess from the frozen picture alone.