[Vega 0.24 / VVD] Audio-only URL playback eventually fails with MEDIA_ERR_SRC_NOT_SUPPORTED (code 4)

Title:
[Vega 0.24 / VVD] Audio-only URL playback eventually fails with MEDIA_ERR_SRC_NOT_SUPPORTED (code 4)

Hi,

I’m seeing a repeatable media playback failure while testing an audio-only
React Native Kepler app on Vega Virtual Device.

Environment:

  • Vega 0.24
  • React Native Kepler 4.0.1
  • React Native 0.83
  • @amazon-devices/react-native-w3cmedia 2.x
  • Release VPKG
  • audio-only AAC-LC .m4a
  • HTTPS CloudFront URL
  • URL Mode / VideoPlayer
  • no video track

Behavior:

The same Release VPKG and the same media URL can initially play correctly.

After using the Vega Virtual Device for some time, playback can begin failing
with:

MEDIA_ERR_SRC_NOT_SUPPORTED (code 4)

At that point the app shows:

0:00 / 0:00

and retrying the same source does not recover playback.

Previously, restarting the Vega Virtual Device sometimes restored playback.
However, I have now also seen cases where completely restarting VVD does NOT
restore it.

No application code, package, codec, or media URL changed between the working
and failing states.

Because the identical Release VPKG and identical HTTPS .m4a source can work
and later fail, this appears to be related to media/session state or the
Virtual Device environment, but I cannot confirm the root cause.

I can provide logs, VPKG details, and exact reproduction steps if useful.

Additional observation:

In one failing state, restarting the Vega Virtual Device alone did not restore
playback. Restarting the host macOS system did restore playback with the same
Release VPKG and the same HTTPS AAC-LC .m4a source.

This may indicate that the failing state is not limited to the app process or
the VVD instance itself, and could involve host-side Vega / media / virtual
device state.

Best,
Atsushi

Hi @atsushiyago

First, an important distinction from your earlier thread: since this is audio-only (.m4a, AAC-LC, no video track), the setSurfaceHandle() / KeplerVideoSurfaceView guidance from the other post does not apply here - audio-only URL playback doesn’t require a rendering surface.

The key signals in your report are that
(a) the identical VPKG + URL works and later fails with no code/media change
(b) it degrades over VVD uptime and now sometimes doesn’t recover even after a full VVD restart.
That points away from your app’s code or the media itself and toward media/session state or the Virtual Device environment.

One concrete thing to check on the app side first (it’s the documented media-session requirement on Vega):

  • Make sure you are deinitialize()-ing your player instance when playback ends or the component unmounts, before creating/initializing a new one. Vega has hard media-session constraints - the docs note that a VideoPlayer instance must be deinitialized before a new one is initialized, or the next playback can fail. If your app creates a new player per play (or on retry) without deinitializing the previous one, sessions can accumulate over the VVD’s uptime and later init/src attempts start failing with a generic code 4.
  • Also ensure you release the player when the app is backgrounded (per the same doc), not just on unmount.

If you’re already deinitializing correctly and it still degrades - especially the part where a full VVD restart doesn’t restore playback - that’s the most important detail for us, because an in-process session leak should clear on restart. That behavior suggests something at the VVD environment level, and we’d want to look at it.

To investigate, could you share:

  1. Exact versions: vega --version, @amazon-devices/react-native-w3cmedia version, RN version, and /etc/os-release from the VVD (vega exec vda shell → cat/etc/os-release).
  2. loggingctl log captured across the transition - ideally covering a successful play and then a failing one on the same VVD session - so we can see what the native audio/media pipeline reports at the point it starts returning code 4.
  3. Your player lifecycle: a short snippet of how you create / initialize / set src/ and (importantly) deinitialize the player between plays and on unmount/background.
  4. Repro steps + rough timing: approximately how long / how many plays before it starts failing, and confirmation of the “VVD restart no longer recovers it” case with a timestamp.
  5. Whether the same VPKG behaves the same way on a physical Vega Fire TV device vs. only on VVD - that tells us if this is VVD-specific.

Once we have the player-lifecycle snippet + logs, we’ll be able to tell whether this is a session-cleanup issue on the app side or something to route to engineering for the VVD/media pipeline. Please share the logs and we’ll dig in.

Warm Regards,
Ivy

Hi @atsushiyago

Checking again if you can please share the below:

  1. Exact versions: vega --version, @amazon-devices/react-native-w3cmedia version, RN version, and /etc/os-release from the VVD (vega exec vda shell → cat/etc/os-release).
  2. loggingctl log captured across the transition - ideally covering a successful play and then a failing one on the same VVD session - so we can see what the native audio/media pipeline reports at the point it starts returning code 4.
  3. Your player lifecycle: a short snippet of how you create / initialize / set src/ and (importantly) deinitialize the player between plays and on unmount/background.
  4. Repro steps + rough timing: approximately how long / how many plays before it starts failing, and confirmation of the “VVD restart no longer recovers it” case with a timestamp.
  5. Whether the same VPKG behaves the same way on a physical Vega Fire TV device vs. only on VVD - that tells us if this is VVD-specific.

Once we have the player-lifecycle snippet + logs, we’ll be able to tell whether this is a session-cleanup issue on the app side or something to route to engineering for the VVD/media pipeline. Please share the logs and we’ll dig in.

Warm Regards,
Ivy

Hi Ivy,

Thanks for following up. I was able to gather more details and narrow the reproduction down quite a bit.

  1. Exact versions

Vega SDK:
0.24.9914

Vega CLI:
1.3.4

@amazon-devices/react-native-w3cmedia:
2.3.2

React Native:
0.83.0

VVD /etc/os-release:

NAME=“OS”
OE_VERSION=“4.0.0”
OS_MAJOR_VERSION=“1”
OS_MINOR_VERSION=“2”
RELEASE_ID=“21”
OS_VERSION=“1.2”
BRANCH_CODE=“TV Ship”
BUILD_DESC=“OS 1.2 (TV Ship/101520710)”
BUILD_FINGERPRINT=“1.0.152071.0(9a1d8dfa7da5d600)/101520710N:user/dev-keys”
BUILD_VARIANT=“user”
BUILD_TAGS=“dev-keys”
BUILD_DATE=“Wed Jul 15 22:17:13 UTC 2026”
BUILD_TIMESTAMP=“1784153833”
VERSION_NUMBER=“2111172071030”

  1. loggingctl capture

I was able to capture another MediaError 4 occurrence with:

vega exec vda shell loggingctl log -o short-precise -f

The UI showed:

VIDEO UNAVAILABLE
MediaError 4: No diagnostic message
0:00 / 0:00

The failure occurred at approximately 09:16:34 UTC on Sep 16 (18:16 JST), and I stopped logging immediately afterward.

I will attach the full loggingctl capture.

A few things I noticed in the same time window:

  • PlayerSessionManagerImpl logged several:
    “EventHook unintended callback for playback state”
  • W3CMEDIA logged HtmlMediaElement::pause.
  • A separate component,
    com.amazondeveloper.keplervideoapp.onInstallOrUpdateTask,
    crashed with SIGSEGV twice in the same general window.

I am not assuming any of those events are causal, but I am mentioning them in case they are useful when reviewing the full log.

  1. Player lifecycle

There is one VideoPlayer instance retained for the lifetime of the React hook.

The app does NOT autoplay on entry. App.tsx calls:

const playback = usePlayback(activeMediaUri, undefined, false);

However, on mount, usePlayback still initializes the player and prepares the source:

initialize()
→ player.src = uri
→ player.load()

Normal playback, pause/resume, source reloads, and Retry reuse the same initialized VideoPlayer instance.

The player is not deinitialized between normal plays or Retry operations.

When the app moves to the background:

  • pause()
  • deinitialize()

When returning to foreground:

  • initialize() again

On unmount:

  • pause()
  • deinitialize()

initialize/deinitialize operations are serialized through a Promise chain, and a generation value is used so callbacks from a retired session are ignored.

The lifecycle helper is:

export class PlayerLifecycle {
private chain: Promise = Promise.resolve();
private generation = 0;
private initialized = false;

private enqueue(operation: () => Promise): Promise {
const result = this.chain.then(operation, operation);
this.chain = result.then(() => undefined, () => undefined);
return result;
}

initialize(player: NativePlayerLifecycle): Promise {
const session = ++this.generation;
return this.enqueue(async () => {
if (!this.initialized) {
await player.initialize();
this.initialized = true;
}
return session;
});
}

deinitialize(player: NativePlayerLifecycle): Promise {
const retiredSession = ++this.generation;
return this.enqueue(async () => {
if (this.initialized) {
await player.deinitialize();
this.initialized = false;
}
return retiredSession;
});
}

isCurrent(session: number): boolean {
return this.initialized && session === this.generation;
}
}

Retry intentionally reloads the existing initialized player rather than deinitializing/reinitializing it.

  1. Reproduction pattern

After more testing, I need to correct my earlier impression about the failure appearing after repeated playback.

The issue now appears specifically related to a full VVD cold start.

Case A:

vega virtual-device start

→ launch Orchestra Lens immediately
→ MediaError 4 occurs

I can reproduce this shortly after the VVD is started.

Case B:

vega virtual-device start

→ wait approximately 1 minute
→ launch Orchestra Lens
→ playback works normally

Case C:

vega device reboot --device VirtualDevice

→ launch Orchestra Lens immediately after reboot
→ playback works normally

I repeated the reboot case several times and could not reproduce MediaError 4.

Also, once playback succeeds in a VVD session, repeatedly pausing and playing again has not reproduced the error for me.

So far, I do not see a correlation with the number of plays or elapsed playback time.

This looks more correlated with the first media initialization/load shortly after a full vega virtual-device start.

One additional UI detail: when the failing startup happens, Orchestra Lens remains in its own “Preparing recording…” state before MediaError 4 appears. That text simply means playback.ready is still false in the application.

  1. Physical device

I have only reproduced this on the Vega Virtual Device.

I do not currently have a physical Vega Fire TV device available for comparison.

One correction to my earlier report:

I can no longer reproduce the case where a VVD restart itself does not recover playback.

A guest reboot using:

vega device reboot --device VirtualDevice

works normally for me.

The reproducible distinction appears to be between a full VVD cold start using vega virtual-device start and a reboot of an already-running VVD.

Please let me know if you would like a more targeted loggingctl capture around the cold-start case, or any additional lifecycle logging.

I’ve also attached:

  • FRICTION_LOG.md, which documents the issue history and troubleshooting
  • orchestra-vvd.log, the full loggingctl capture from the reproduced MediaError 4 case

Warm regards,
Atsushi Yago

(attachments)

FRICTION_LOG.md (3.02 KB)
orchestra-vvd.log (555 KB)

Hi @atsushiyago

Thanks - the capture confirms your cold-start theory. In the same session as your MediaError 4:
So on a cold vega virtual-device start, the guest network isn’t ready when you load the HTTPS .m4a, the fetch has no route, and w3cmedia surfaces it as MEDIA_ERR_SRC_NOT_SUPPORTED (4).

App-side workaround: gate the first load() on network reachability, or retry MediaError 4 with backoff (500ms→1s→2s) - since Retry reuses the initialized player, a delayed retry should succeed.

I’m checking this internally and will update you ASAP.

Warm Regards,
Ivy