Live Widevine DASH on OS 1.2 (48N): intermittent stalls with full buffer — `MediaKeysMgr::get_session_id_for_key failed` after a usable key is registered

# :backhand_index_pointing_right: Bug Description

—

## 1. Summary

On OS 1.2 (TV Ship/48, fingerprint `4.0.476660.0(3072cab629675a74)/48N`), a live DASH stream protected with Widevine (`cenc`, HW_SECURE_ALL, in-band key rotation via `pssh`/`seig`) stalls for 4–38 seconds at a time, every one to three minutes, while 24–36 seconds of media are already buffered at and ahead of the playhead and the network is healthy. At each stall the W3C media layer logs `MediaKeysMgr::get_session_id_for_key failed` and `TrackBufferReader::try_flush_queue: Missing key ID for video sample, waiting for key to be registered…` immediately after an `encrypted` event, the element emits `waitingforkey`, time updates stop while the element stays in Playing state, and the decoder sample queue drains to zero. No new license is requested because the key is already present: the license for the new key period was received and `onKeyStatusChanged … hasUsableKey = 1` was logged 6 seconds before the lookups started failing. Playback resumes only after repeated seeks from the player’s stall detector. Stalls are longest in the 15 seconds after a DRM key rotation (22 s stall 11 s after rotation) but also occur with no rotation nearby, starting about one minute after load.

Impact: live TV in the app freezes repeatedly for the viewer. The permanent decoder freeze we had on OS 1.1 after key rotation is gone on 1.2, but this replaces it. Thread #29181 (2026-10-01) says an upcoming build addresses the crash/freeze; our two soak sessions on 48N show it is still present on 48N.

**App Name**: STARZ (`com.starz.starzplay.firetv`)

**App Link on Amazon Appstore**: `[fill in from Developer Console]`

**Bug Severity**

* [x] Impacts operation of app

* [ ] Blocks current development

* [ ] Improvement suggestion

* [ ] Issue with documentation

* [ ] Other

## 2. Steps to Reproduce

1. Fire TV Stick on OS 1.2 build 48N (`os-release.txt`), armv7.

2. Load a live DASH stream with Widevine, `videoRobustness: ‘HW_SECURE_ALL’`, `audioRobustness: ‘HW_SECURE_CRYPTO’`, where the MPD carries no `cenc:default_KID`/`pssh` and every media segment carries in-band `pssh` + `seig`/`sgpd` boxes (content key rotates ~every 15 minutes). Our stream URL and a test account are shared privately.

3. Play continuously, no user input. Stream the device log: `loggingctl log -f -v com.starz.starzplay.firetv`.

4. Within ~2 minutes the first stall appears with `E W3CMEDIA:MediaKeysMgr::get_session_id_for_key failed`. Stalls recur every 1–3 minutes. Around the 15-minute key rotation they get longer.

5. The player is Shaka 4.8.5 on `@amazon-devices/react-native-w3cmedia`, loaded through the inline (`VideoPlayer` surface) path; config snippet in section 7. No app-side recovery logic was active during the test run (our rotation workaround was disabled so the platform behaviour is unmodified).

## 3. Observed Behavior

```

Session 2026-10-02 21:26–21:58 UTC, one continuous live session, 1080p rung throughout, no app-side reloads.

Stall start Length Key-lookup failures Media buffered ahead of playhead

21:27:55 38 s 5 25–33 s

21:29:01 22 s 7 24–36 s

21:32:13 10 s 3 30–36 s

21:35:55 28 s 9 30–36 s

21:37:02 17 s 5 30–36 s

21:53:20 15 s 5 24–36 s

21:54:14 22 s 7 24–36 s ← 11 s after license rotation at 21:54:03

21:55:08 10 s 3 24–36 s

(+ ~10 more stalls of 4–10 s; full list in stall-episodes.txt)

Session totals: 436 `encrypted` events, 91 `waitingforkey`, 89 `get_session_id_for_key failed`,

88 `Missing key ID`, 4 license requests, 0 Shaka errors, 1 key rotation, 0 app reloads.

During every stall:

- playhead inside the buffered range, 17–40 s past its start, 24–36 s before its end (getBufferedRange)

- segment fetches steady at ~10 video segments/min; device download speed on a live segment 2.5 MB/s

- element state Playing; no MSE/EME error raised; `No Time update even in Playing state` every 250 ms

- `MPB UNF … sampleQueueDepth (0) < (400)` (decoder sample queue empty)

- recovery only after repeated `PipelineImpl::seek` from the player’s stall detector; no new license request

Verbatim around the rotation (full window in device-log-2026-10-02-2153-2156-raw.log.gz):

21:54:03.275 [ShakaPlayer] license rotation detected at t=1593.4s

21:54:03.280 W3CMEDIA:update:license response size: 764

21:54:03.307 W3CMEDIA:onKeyStatusChanged: sessionId=ksid8AE752A5

21:54:03.311 W3CMEDIA:Calling KeyStatus changed with hasUsableKey = 1

21:54:09.162 W3CMEDIA:[MSE_EME] SourceBufferStateImpl::on_encrypted_media_init_data: Encrypted media is received

21:54:09.162 W3CMEDIA:Emitting event: source = HtmlMediaElement name = encrypted

21:54:09.950 E W3CMEDIA:MediaKeysMgr::get_session_id_for_key failed

21:54:09.950 W W3CMEDIA:[MSE_EME] TrackBufferReader::try_flush_queue: Missing key ID for video sample, waiting for key to be registered…

21:54:14.151 W3CMEDIA:Emitting event: source = HtmlMediaElement name = waitingforkey

21:54:14.639 W W3CMEDIA:[MSE_EME] MediaElement::push_time_update_event(): No Time update even in Playing state: 35898044.959000

21:54:15.491 W3CMEDIA:[MSE_EME] PipelineImpl::seek: Seek time: 35898045.059000s

21:54:15.606 W W3CMEDIA:[MPB_DRM] MPB UNF callback: MPBBufferingMonitorImpl : trackID=0: sampleQueueDepth (0) < (400). BM state=2

21:54:19.609 W3CMEDIA:[MSE_EME] PipelineImpl::seek: Seek time: 35898050.321833s

21:54:19.652 E W3CMEDIA:MediaKeysMgr::get_session_id_for_key failed

21:54:19.652 W W3CMEDIA:[MSE_EME] TrackBufferReader::try_flush_queue: Missing key ID for video sample, waiting for key to be registered…

(the failed/Missing-key pair repeats on every seek until playback resumes)

```

## 4. Expected Behavior

```

Buffered, decryptable samples play without interruption. After a key rotation, once the new

license is applied and the key is reported usable, samples carrying that key ID are mapped to

their session and decoded; the element does not enter waitingforkey for a key it already has.

In-band key rotation (pssh + seig sample groups) on a live stream should be seamless, as it is

on the same content on other platforms and on this platform for VOD.

```

### 4.a Possible Root Cause & Temporary Workaround

```

Root cause (suspected, platform side): MediaKeysMgr::get_session_id_for_key intermittently fails to

map a sample’s key ID to the CDM session that holds it, although that session has reported a

usable key. Possibly related to two key periods being present in the source buffer at once

(timeShiftBufferDepth 58.5 s spans a key boundary) — Amazon’s reply in #29181 also pointed at

key-rotation binding in the decrypt pipeline.

Ruled out on our side: network (2.5 MB/s, steady fetch cadence, 0 Shaka network/manifest errors),

buffer underrun (24–36 s buffered at the playhead), app intervention (none during the run),

SDK version (#29181 reproduces on 0.24.9914, we are on 0.22). Yesterday’s session with our

workaround enabled shows the same key-lookup lines at lower frequency.

Temporary workaround: none for the stalls. For the OS 1.1 permanent freeze we tear down and

recreate the player 5 s after each license rotation (detected as a LICENSE response >60 s after

load); that costs a ~5–30 s black screen per rotation and does not prevent the stalls above.

Shaka’s default stall detector (seek nudge) is what ends each stall today.

```

## 5. Logs or crash report

No crash in these sessions; this is a playback stall. Attachments (all device UTC; 32-hex tokens redacted):

* `device-log-2026-10-02-2126-2158-filtered.log.gz` — full 10-02 session, filtered to DRM/EME, buffering, seek, position, segment-request and rotation lines

* `device-log-2026-10-02-2153-2156-raw.log.gz` — unfiltered 3-minute window around the 21:54:03 key rotation

* `device-log-2026-10-01-2047-2112-filtered.log.gz` — 10-01 session with our rotation workaround enabled (two reloads visible; same key-lookup lines at lower frequency; that session was Wi-Fi starved so most of its stalls are ordinary underruns)

* `stall-episodes.txt` — every stall ≥1 s in both sessions with length, key-lookup count and buffer position

* `session-counts-2026-10-02.json`, `dash.mpd`, `segment-boxes.txt`, `os-release.txt`, `versions.json`

Note: `loggingctl config --set-level drmserver debug` is refused from the developer shell on this user build (same as #29181), so decrypt-daemon logs are not included.

## 6. Environment

* **SDK Version:** `vega --version` → Active SDK Version 0.22.5875, Vega CLI 1.2.22. App built against Vega SDK 0.22.6021 (`VEGA_SDK_VERSION` in the app env).

* **React Native Version:** RN 0.72.0, `@amazon-devices/react-native-kepler` ~2.0.0, `@amazon-devices/react-native-w3cmedia` ^2.1.66

* **App State:** Foreground (live player screen visible, no user input)

* **OS Information:**

```

NAME=“OS”

OE_VERSION=“4.0.0”

OS_MAJOR_VERSION=“1”

OS_MINOR_VERSION=“2”

RELEASE_ID=“23”

OS_VERSION=“1.2”

BRANCH_CODE=“TV Ship”

BUILD_DESC=“OS 1.2 (TV Ship/48)”

BUILD_FINGERPRINT=“4.0.476660.0(3072cab629675a74)/48N:user/release-keys”

BUILD_VARIANT=“user”

BUILD_TAGS=“release-keys”

BUILD_DATE=“Thu Sep 10 22:05:50 UTC 2026”

```

Device: Fire TV Stick, serial `GT533M0751441WDB`, armv7.

## 7. Example Code Snippet / Screenshots / Screengrabs

Shaka DRM configuration used for the live stream (`src/shakaplayer/ShakaPlayer.ts`):

```ts

player.configure({

drm: {

retryParameters: { maxAttempts: 3, baseDelay: 0, backoffFactor: 1.25, fuzzFactor: 0.25, timeout: 10000 },

servers: { ‘com.widevine.alpha’: content.drm_license_uri },

advanced: {

‘com.widevine.alpha’: {

videoRobustness: ‘HW_SECURE_ALL’,

audioRobustness: ‘HW_SECURE_CRYPTO’,

persistentStateRequired: false,

  },

},

preferredKeySystems: [‘com.widevine.alpha’],

},

streaming: {

lowLatencyMode: false,

inaccurateManifestTolerance: 0,

rebufferingGoal: 0.01,

bufferingGoal: 5,

alwaysStreamText: true,

retryParameters: { maxAttempts: 3 },

infiniteLiveStreamDuration: true,

},

});

```

Screengrab: frozen frame with the player in Playing state (attached on request; the device log is the better record).

—

## :backhand_index_pointing_right: Playback Issues

—

```

Live linear DASH, Widevine HW_SECURE_ALL, armv7 Fire TV Stick. Stream stalls 4–38 s every 1–3 min

with a full buffer; media layer logs get_session_id_for_key failed / Missing key ID for video sample

right after an encrypted event although the key was just reported usable. Pre-conditions: US

geo-location, authenticated STARZ account with live entitlement. Not reproducible on VOD from the

same DRM stack.

```

* **Player SDK:** Shaka Player (vendored compiled build on `@amazon-devices/react-native-w3cmedia`)

* **Player SDK Version:** 4.8.5

* **Audio Codecs:** AAC-LC stereo, 48 kHz (`mp4a.40.2`), 128 kbps

* **Video Codecs:** H.264, 240p–1080p ladder (426x240 @ 750 kbps … 1920x1080 @ 3 Mbps), 29.97 fps

* **Manifest Types:** DASH live (`dash.mpd`), single Period, `minimumUpdatePeriod` PT15S, `timeShiftBufferDepth` PT58.5S, 6 s CMAF segments, WebVTT text track

**Q: If applicable, please provide your media/content url**

```

Shared privately (tokenized Widevine license; stream requires an entitled STARZ test account).

Manifest attached as dash.mpd; one media segment’s box listing attached as segment-boxes.txt

(top-level moof/mdat/styp/sidx; in-band pssh x2, seig x2, sgpd x1, senc x1; no tenc in media segments).

```

**Q: Are there any special headers required to reproduce the issue you are facing?**

```

License requests: content-type application/octet-stream to the Widevine license server

(set via a Shaka request filter). Segment and manifest requests: none.

```

**Additionally please provide the following if possible**

```

See section 5 attachments. stall-episodes.txt gives every stall with buffer position; the raw

3-minute window shows the full sequence around one key rotation.

```

—

## :backhand_index_pointing_right: Additional Context

—

```

- Same OS build and symptom evolution as https://community.amazondeveloper.com/t/.../29181

(LA7: SIGSEGV in app-demux-source on 48N, then “live-freeze instead”, Amazon reply 2026-10-01:

“updated build in an upcoming update … should address the crash/freeze”). We are on SDK 0.22

and see the freeze phase on 48N; #29181 is on SDK 0.24. Please tell us the build number that

carries the fix and whether it covers the key-lookup failure above or only the SIGSEGV.

- On OS 1.1 the same stream froze permanently 10–126 s after each key rotation with no MSE/EME

error; the OS 1.2/48N behaviour above is what remains with our workaround disabled.

- Key rotation every 15 minutes is a content-protection requirement on our side and cannot be

removed or lengthened.

- A 2026-10-01 session on the same device also logged one foreground app kill (LCM_KILLREASON

empty, device journal rotated before it could be read); we could not tie it to this issue and

are not reporting it here.

```

Hi @Phi_Huynh,

Thank you for another exceptionally detailed and well-instrumented report - the per-stall table, the verbatim rotation window, the ruled-out layers, and the session counts are extremely helpful, and the correlation you’ve drawn between the OS 1.1 permanent-freeze behavior and the new 48N intermittent-stall behavior is clear.

Your evidence precisely characterizes the failure: get_session_id_for_key failed / Missing key ID immediately after an encrypted event, despite hasUsableKey = 1 logged ~6 s earlier, with a full buffer, the element still in Playing state, and no MSE/EME error raised. That points to the native decrypt/decode path intermittently failing to map a sample’s key ID to the CDM session holding the rotated key, rather than anything in your app, network, or Shaka configuration (which your data rules out cleanly).

I’ve shared your report and your 48N soak-session findings with the media team, and specifically asked them to confirm:

  1. The build number that carries the key-rotation fix, and
  2. Whether that fix addresses this get_session_id_for_key key-lookup failure, or only the permanent-freeze/crash symptom.

I’ll follow up here as soon as I have that information from them.

To help the team’s investigation, the most valuable addition would be decrypt-layer logs captured during a key-rotation stall. You noted that drmserver log-level is refused on the user build - if you’re able to surface any decrypt/CDM-layer logging through another process or log level on 48N, those lines would materially help confirm whether the rotated key is being applied to the new segments. If no decrypt-layer logging can be enabled on this build, please let us know, as that limitation is itself useful signal.

Could you also confirm:

  • @amazon-devices/react-native-w3cmedia version (you listed ^2.1.66 - please confirm the exact resolved version), and
  • Whether the same 48N build shows the behavior on any other live Widevine stream, or only this one.

Best regards,
Aishwarya

I sent the attachments through Slack to Varun Jayakumar and Gomathy Sampath for them to pass along the files to you guys because I can’t upload here.

Confirming both points.

1. @amazon-devices/react-native-w3cmedia resolved version: 2.1.87.
The ^2.1.66 in my report was the range in package.json. The installed package and package-lock.json both resolve to 2.1.87, from https://registry.npmjs.org/@amazon-devices/react-native-w3cmedia/-/react-native-w3cmedia-2.1.87.tgz. I have corrected the attached versions.json and the report text. For completeness: @amazon-devices/react-native-kepler ~2.0.0, React Native 0.72.0, Shaka Player 4.8.5, app built against Vega SDK 0.22.6021, vega --version on the build machine reports Active SDK 0.22.5875 and CLI 1.2.22.

2. Other live Widevine streams: we only have one, so I cannot compare across streams on 48N.
Our app carries a single live linear channel, the STARZ feed described in the report, currently available only in our development environment. Every observation in the report comes from that one stream. What I can say about scope:

  • VOD titles from the same DRM stack, same license server and same HW_SECURE_ALL configuration play without this behaviour on the same 48N device.
  • The same live stream on OS 1.1 showed a different failure, a permanent decoder freeze 10 to 126 seconds after each key rotation. On 48N that is gone and the key-lookup stalls described in the report are what remains.
  • A second session on 48N the previous day, with our rotation workaround enabled, showed the same get_session_id_for_key failed lines at lower frequency, so it is not specific to one session.

If you can point me at a reference live Widevine DASH stream with in-band key rotation that you consider representative, I will run the same soak on this 48N device and attach the result so you have a second-stream data point.

Hi @Phi_Huynh,

Our team investigated your logs and traced these key-rotation stalls to a known media-pipeline issue that’s already fixed in a newer OS release. The 48N build you’re on predates that fix.

As a next step to validate on your stream, could you update the device to the latest available OS and retest the same live soak? A build carrying the fix is available over the air.

Your genuine ~15-min in-band rotation is exactly the scenario we want to confirm against, so your retest is the ideal validation. If the stalls persist after updating, grab the same logs again and we’ll pick the investigation back up.

Best regards,
Aishwarya