RocketChat/Rocket.Chat · warning
Failed to start audio playback:
Error message
Failed to start audio playback:
What it means
Client-side: the media player assigned a new track to an <audio> element (src + load()) and called play(); the returned promise rejected. Browsers reject play() with NotAllowedError when autoplay is blocked (no prior user gesture), NotSupportedError when the source cannot be decoded, or AbortError when a new load interrupts the play request. The warn is console-only and the player simply stays paused.
Source
Thrown at apps/meteor/client/providers/MediaPlayerProvider/MediaPlayerProvider.tsx:56
}, []);
const setAudioRef = useMergedRefs(audioCallback, mediaRef);
const play = useStableCallback((next: PersistentAudioTrack) => {
const audio = audioRef.current;
if (!audio) {
return;
}
if (trackRef.current?.id !== next.id) {
setTrack(next);
setCurrentTime(0);
setDuration(0);
audio.src = next.url;
audio.load();
}
audio.playbackRate = playbackRate;
audio.play().catch((err) => console.warn('Failed to start audio playback:', err));
});
const toggle = useStableCallback(() => {
const audio = audioRef.current;
if (!audio || !trackRef.current) {
return;
}
if (audio.paused) {
audio.play().catch((err) => console.warn('Failed to resume audio playback:', err));
} else {
audio.pause();
}
});
const seek = useStableCallback((time: number) => {
const audio = audioRef.current;
if (!audio) {
return;View on GitHub (pinned to b2c16d5842)
Solutions
- Start playback from a user gesture (the play/toggle button); programmatic starts are the ones autoplay policy blocks
- Check the network tab: the audio request must return 200 with a proper audio content-type
- Refresh expired file URLs before assigning audio.src
- Serve widely supported codecs and handle NotAllowedError by showing a paused player the user can click
Defensive patterns
Strategy: try-catch
Type guard
function isAutoplayBlocked(err: unknown): err is DOMException {
return err instanceof DOMException && err.name === 'NotAllowedError';
} Try / catch
audio.play().catch((err: unknown) => {
if (err instanceof DOMException && err.name === 'NotAllowedError') {
setPausedState(); // show a play button for the user to click
return;
}
console.warn('Failed to start audio playback:', err);
}); Prevention
- Only call play() inside a user-gesture handler for the first playback; programmatic starts get blocked
- Refresh expiring media URLs before assigning audio.src
- Handle NotAllowedError, NotSupportedError and AbortError separately instead of logging blindly
When it happens
Trigger: Playback started programmatically (effect on track change) without a qualifying user interaction; audio URL 404/403 (expired file-upload auth links); unsupported codec or wrong content-type from the server; rapid track switches aborting the previous play() call.
Common situations: Chrome/Safari autoplay policies on fresh tabs or direct deep-links; long-lived sessions where file URLs expire; proxies stripping Accept-Ranges or content-type on audio responses.
Related errors
- Failed to resume audio playback:
- Failed to resume playback after URL recovery:
- [Message Delivery] High delay detected: ${receiveDelay}ms. P
- Command does not exist in the system currently (or it is dis
- Invalid Slash Command parameter provided, it must be a valid
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/1dbb488d08d36e7f.
Report an issue: GitHub.