RocketChat/Rocket.Chat · warning
Failed to resume audio playback:
Error message
Failed to resume audio playback:
What it means
Client-side: the player's toggle handler called audio.play() to resume a paused track and the promise rejected. Unlike programmatic starts, this runs inside a user gesture, so the usual causes are media-level failures: source unloaded or expired (src removed, link expired), the fetch of media data aborted by a new load request, or the element left in a state where play() cannot start.
Source
Thrown at apps/meteor/client/providers/MediaPlayerProvider/MediaPlayerProvider.tsx:65
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;
}
audio.currentTime = Math.max(0, Math.min(time, audio.duration || time));
});
const cyclePlaybackRate = useStableCallback(() => {
setPlaybackRate((rate) => {
const idx = PLAYBACK_RATES.indexOf(rate as (typeof PLAYBACK_RATES)[number]);
const nextRate = PLAYBACK_RATES[(idx + 1) % PLAYBACK_RATES.length];
if (audioRef.current) {View on GitHub (pinned to b2c16d5842)
Solutions
- Check the err.name in console: AbortError is a benign race — retry play(); NotSupportedError means the source is bad
- Re-set audio.src with a fresh URL before resuming if links can expire
- Avoid starting a new load while a play() promise is pending; chain the operations instead
- For unrecoverable sources, surface an error state in the UI instead of retrying
Defensive patterns
Strategy: try-catch
Type guard
function isAbortError(err: unknown): err is DOMException {
return err instanceof DOMException && err.name === 'AbortError';
} Try / catch
audio.play().catch((err: unknown) => {
if (isAbortError(err)) return; // benign: superseded by a new load request
if (err instanceof DOMException && err.name === 'NotSupportedError') {
showSourceErrorUI();
return;
}
console.warn('Failed to resume audio playback:', err);
}); Prevention
- Do not start a new load() while a play() promise is pending on the same element
- Re-acquire fresh signed URLs for long-paused audio before resume
- Classify DOMException names (AbortError/NotAllowedError/NotSupportedError) rather than treating all rejections alike
When it happens
Trigger: Resuming after the underlying file URL expired; pressing play while a track switch is mid-load (AbortError: play() interrupted by a new load request); playbackRate or currentTime set to an unsupported value before resume; source removed from the element while paused.
Common situations: Audio attachments whose authenticated URLs expire during a long pause; quick toggle/track-change races; mobile browsers unloading media to save memory.
Related errors
- Failed to start 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/f0788a76f32935af.
Report an issue: GitHub.