{"record":{"id":"9b18d3b741a11ae8","repo":"bilibili/flv.js","slug":"htmlmediaelement-must-be-attached-before-load","errorCode":null,"errorMessage":"HTMLMediaElement must be attached before load()!","messagePattern":"HTMLMediaElement must be attached before load\\(\\)!","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/player/flv-player.js","lineNumber":189,"sourceCode":"    detachMediaElement() {\n        if (this._mediaElement) {\n            this._msectl.detachMediaElement();\n            this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata);\n            this._mediaElement.removeEventListener('seeking', this.e.onvSeeking);\n            this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay);\n            this._mediaElement.removeEventListener('stalled', this.e.onvStalled);\n            this._mediaElement.removeEventListener('progress', this.e.onvProgress);\n            this._mediaElement = null;\n        }\n        if (this._msectl) {\n            this._msectl.destroy();\n            this._msectl = null;\n        }\n    }\n\n    load() {\n        if (!this._mediaElement) {\n            throw new IllegalStateException('HTMLMediaElement must be attached before load()!');\n        }\n        if (this._transmuxer) {\n            throw new IllegalStateException('FlvPlayer.load() has been called, please call unload() first!');\n        }\n        if (this._hasPendingLoad) {\n            return;\n        }\n\n        if (this._config.deferLoadAfterSourceOpen && this._mseSourceOpened === false) {\n            this._hasPendingLoad = true;\n            return;\n        }\n\n        if (this._mediaElement.readyState > 0) {\n            this._requestSetTime = true;\n            // IE11 may throw InvalidStateError if readyState === 0\n            this._mediaElement.currentTime = 0;\n        }","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/bilibili/flv.js/blob/42343088f22619cf014a057b3878fe3d320016a6/src/player/flv-player.js#L171-L207","documentation":"FlvPlayer.load() requires an HTMLMediaElement to have been attached via attachMediaElement() first, because MSECTL and the media element wiring are created during attachment. Calling load() without attachment throws IllegalStateException so the pipeline is not started against a missing output.","triggerScenarios":"Calling player.load() (directly or via attachMediaElement's flow) when this._mediaElement is null — i.e. creating the player with flvjs.createPlayer() but never calling player.attachMediaElement(videoEl) — at src/player/flv-player.js:189.","commonSituations":"Headless/background initialization that defers DOM attachment, attaching the video element after an async step but calling load() before it resolves, or forgetting attachMediaElement entirely.","solutions":["Call player.attachMediaElement(videoElement) before player.load().","Reorder code so load() runs after the media element exists in the DOM.","If load() may be invoked from multiple places, check player._mediaElement or wrap in try/catch for IllegalStateException."],"exampleFix":"// before\nconst player = flvjs.createPlayer(source);\nplayer.load();\n// after\nconst player = flvjs.createPlayer(source);\nplayer.attachMediaElement(document.querySelector('video'));\nplayer.load();","handlingStrategy":"validation","validationCode":"function safeLoad(player, videoEl) {\n    if (!videoEl || !(videoEl instanceof HTMLMediaElement)) {\n        throw new Error('video element required before load()');\n    }\n    player.attachMediaElement(videoEl);\n    player.load();\n}","typeGuard":"function isAttached(player) {\n    return player._mediaElement instanceof HTMLMediaElement;\n}","tryCatchPattern":"try {\n    player.load();\n} catch (e) {\n    if (/must be attached before load/.test(e.message)) {\n        player.attachMediaElement(videoEl);\n        player.load();\n    } else throw e;\n}","preventionTips":["Adopt a fixed init order: createPlayer -> attachMediaElement -> load.","Wrap async init so load() only runs after the <video> element is resolved.","Assert the media element exists in DOM before initializing playback."],"tags":["player","lifecycle","api-misuse","state"],"backgroundTag":"media-element-not-attached","analyzedSha":"42343088f22619cf014a057b3878fe3d320016a6","analyzedAt":"2026-09-01T00:27:28.147Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}