bilibili/flv.js · error · IllegalStateException

HTMLMediaElement must be attached before load()!

Error message

HTMLMediaElement must be attached before load()!

What it means

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.

Source

Thrown at src/player/flv-player.js:189

    detachMediaElement() {
        if (this._mediaElement) {
            this._msectl.detachMediaElement();
            this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata);
            this._mediaElement.removeEventListener('seeking', this.e.onvSeeking);
            this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay);
            this._mediaElement.removeEventListener('stalled', this.e.onvStalled);
            this._mediaElement.removeEventListener('progress', this.e.onvProgress);
            this._mediaElement = null;
        }
        if (this._msectl) {
            this._msectl.destroy();
            this._msectl = null;
        }
    }

    load() {
        if (!this._mediaElement) {
            throw new IllegalStateException('HTMLMediaElement must be attached before load()!');
        }
        if (this._transmuxer) {
            throw new IllegalStateException('FlvPlayer.load() has been called, please call unload() first!');
        }
        if (this._hasPendingLoad) {
            return;
        }

        if (this._config.deferLoadAfterSourceOpen && this._mseSourceOpened === false) {
            this._hasPendingLoad = true;
            return;
        }

        if (this._mediaElement.readyState > 0) {
            this._requestSetTime = true;
            // IE11 may throw InvalidStateError if readyState === 0
            this._mediaElement.currentTime = 0;
        }

View on GitHub (pinned to 42343088f2)

Solutions

  1. Call player.attachMediaElement(videoElement) before player.load().
  2. Reorder code so load() runs after the media element exists in the DOM.
  3. If load() may be invoked from multiple places, check player._mediaElement or wrap in try/catch for IllegalStateException.

Example fix

// before
const player = flvjs.createPlayer(source);
player.load();
// after
const player = flvjs.createPlayer(source);
player.attachMediaElement(document.querySelector('video'));
player.load();
Defensive patterns

Strategy: validation

Validate before calling

function safeLoad(player, videoEl) {
    if (!videoEl || !(videoEl instanceof HTMLMediaElement)) {
        throw new Error('video element required before load()');
    }
    player.attachMediaElement(videoEl);
    player.load();
}

Type guard

function isAttached(player) {
    return player._mediaElement instanceof HTMLMediaElement;
}

Try / catch

try {
    player.load();
} catch (e) {
    if (/must be attached before load/.test(e.message)) {
        player.attachMediaElement(videoEl);
        player.load();
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of bilibili/flv.js@42343088f2 (2026-09-01). Data as JSON: /api/errors/9b18d3b741a11ae8. Report an issue: GitHub.