{"record":{"id":"e5f00ecf37529db4","repo":"bilibili/flv.js","slug":"htmlmediaelement-must-be-attached-before-load-e5f00e","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/native-player.js","lineNumber":117,"sourceCode":"        }\n    }\n\n    detachMediaElement() {\n        if (this._mediaElement) {\n            this._mediaElement.src = '';\n            this._mediaElement.removeAttribute('src');\n            this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata);\n            this._mediaElement = null;\n        }\n        if (this._statisticsReporter != null) {\n            window.clearInterval(this._statisticsReporter);\n            this._statisticsReporter = null;\n        }\n    }\n\n    load() {\n        if (!this._mediaElement) {\n            throw new IllegalStateException('HTMLMediaElement must be attached before load()!');\n        }\n        this._mediaElement.src = this._mediaDataSource.url;\n\n        if (this._mediaElement.readyState > 0) {\n            this._mediaElement.currentTime = 0;\n        }\n\n        this._mediaElement.preload = 'auto';\n        this._mediaElement.load();\n        this._statisticsReporter = window.setInterval(\n            this._reportStatisticsInfo.bind(this),\n        this._config.statisticsInfoReportInterval);\n    }\n\n    unload() {\n        if (this._mediaElement) {\n            this._mediaElement.src = '';\n            this._mediaElement.removeAttribute('src');","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/bilibili/flv.js/blob/42343088f22619cf014a057b3878fe3d320016a6/src/player/native-player.js#L99-L135","documentation":"NativePlayer.load() drives playback by assigning the media URL to an HTMLMediaElement that was previously passed to attachMediaElement(). If no media element is attached, there is nothing to load into, so load() throws IllegalStateException. The API contract requires attachMediaElement() before any load() call.","triggerScenarios":"Calling player.load() without ever calling player.attachMediaElement(videoEl), or after calling detachMediaElement()/destroy() which nulls this._mediaElement.","commonSituations":"Skipping the attach step in setup code; calling load() after a destroy()/re-init cycle; attaching inside an async callback that hasn't resolved yet while load() is invoked synchronously; reusing a destroyed player instance.","solutions":["Call player.attachMediaElement(document.querySelector('video')) before player.load()","Ensure attach happens before load() in async setup code (attach in a .then() before invoking load)","If the player was destroyed, create a new instance instead of reusing it","Guard the call: only invoke load() when a media element is still attached"],"exampleFix":"// before\nconst player = flvjs.createPlayer({ type: 'flv', url: 'http://example.com/live.flv' });\nplayer.load(); // throws: HTMLMediaElement must be attached before load()!\n\n// after\nconst player = flvjs.createPlayer({ type: 'flv', url: 'http://example.com/live.flv' });\nplayer.attachMediaElement(document.getElementById('videoElement'));\nplayer.load();","handlingStrategy":"try-catch","validationCode":"if (!player._mediaElement /* or track attachment yourself */) {\n  player.attachMediaElement(document.getElementById('videoElement'));\n}\nplayer.load();\n\n// cleaner: track attachment in your own code\nlet attached = false;\nplayer.attachMediaElement(videoEl); attached = true;\nif (attached) player.load();","typeGuard":"function isAttached(player) {\n  return player != null && typeof player.attachMediaElement === 'function' && !!player._mediaElement;\n}","tryCatchPattern":"try {\n  player.load();\n} catch (e) {\n  if (e instanceof flvjs.CustomException || /must be attached/.test(e.message)) {\n    player.attachMediaElement(videoElement);\n    player.load();\n  } else {\n    throw e;\n  }\n}","preventionTips":["Always call attachMediaElement() immediately after createPlayer() and before load()","Follow the documented order: createPlayer -> attachMediaElement -> load -> play","Never call load() after destroy(); create a fresh player instance instead","If setup is async, attach the element inside the same async flow before triggering load"],"tags":["javascript","media","lifecycle","flv-js","player"],"backgroundTag":"attach-before-load","analyzedSha":"42343088f22619cf014a057b3878fe3d320016a6","analyzedAt":"2026-09-01T00:27:28.147Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}