{"record":{"id":"1dbb488d08d36e7f","repo":"RocketChat/Rocket.Chat","slug":"failed-to-start-audio-playback","errorCode":null,"errorMessage":"Failed to start audio playback:","messagePattern":"Failed to start audio playback:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/meteor/client/providers/MediaPlayerProvider/MediaPlayerProvider.tsx","lineNumber":56,"sourceCode":"\t}, []);\n\tconst setAudioRef = useMergedRefs(audioCallback, mediaRef);\n\n\tconst play = useStableCallback((next: PersistentAudioTrack) => {\n\t\tconst audio = audioRef.current;\n\t\tif (!audio) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (trackRef.current?.id !== next.id) {\n\t\t\tsetTrack(next);\n\t\t\tsetCurrentTime(0);\n\t\t\tsetDuration(0);\n\t\t\taudio.src = next.url;\n\t\t\taudio.load();\n\t\t}\n\n\t\taudio.playbackRate = playbackRate;\n\t\taudio.play().catch((err) => console.warn('Failed to start audio playback:', err));\n\t});\n\n\tconst toggle = useStableCallback(() => {\n\t\tconst audio = audioRef.current;\n\t\tif (!audio || !trackRef.current) {\n\t\t\treturn;\n\t\t}\n\t\tif (audio.paused) {\n\t\t\taudio.play().catch((err) => console.warn('Failed to resume audio playback:', err));\n\t\t} else {\n\t\t\taudio.pause();\n\t\t}\n\t});\n\n\tconst seek = useStableCallback((time: number) => {\n\t\tconst audio = audioRef.current;\n\t\tif (!audio) {\n\t\t\treturn;","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/client/providers/MediaPlayerProvider/MediaPlayerProvider.tsx#L38-L74","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isAutoplayBlocked(err: unknown): err is DOMException {\n\treturn err instanceof DOMException && err.name === 'NotAllowedError';\n}","tryCatchPattern":"audio.play().catch((err: unknown) => {\n\tif (err instanceof DOMException && err.name === 'NotAllowedError') {\n\t\tsetPausedState(); // show a play button for the user to click\n\t\treturn;\n\t}\n\tconsole.warn('Failed to start audio playback:', err);\n});","preventionTips":["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"],"tags":["audio","browser","autoplay","client","media","html5-audio"],"backgroundTag":"autoplay-blocked","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}