bilibili/flv.js · critical · RuntimeException

IOException: ' + data.msg

Error message

IOException: ' + data.msg

What it means

When a loader error reaches IOController._onLoaderError and no user-supplied onError callback is registered, the controller has nowhere to report the failure and throws RuntimeException('IOException: ' + data.msg). The library surfaces the underlying loader error message (e.g. network failure, HTTP error, early EOF) as an uncaught exception.

Source

Thrown at src/io/io-controller.js:641

                        return;
                    }
                    // else: We don't know totalLength, throw UnrecoverableEarlyEof
                }
                // live stream: throw UnrecoverableEarlyEof error to upper-layer
                type = LoaderErrors.UNRECOVERABLE_EARLY_EOF;
                break;
            }
            case LoaderErrors.UNRECOVERABLE_EARLY_EOF:
            case LoaderErrors.CONNECTING_TIMEOUT:
            case LoaderErrors.HTTP_STATUS_CODE_INVALID:
            case LoaderErrors.EXCEPTION:
                break;
        }

        if (this._onError) {
            this._onError(type, data);
        } else {
            throw new RuntimeException('IOException: ' + data.msg);
        }
    }

}

export default IOController;

View on GitHub (pinned to 42343088f2)

Solutions

  1. Register an error callback so the library reports errors instead of throwing: pass/assign onError (flvPlayer.on(flvjs.Events.ERROR, handler) or the IOController._onError hook).
  2. Inspect data.msg in the thrown message to identify the root cause (network vs HTTP status).
  3. Add retry/reconnect logic in your error handler for transient network failures.

Example fix

// before
const player = flvjs.createPlayer(mediaDataSource);
player.attachMediaElement(video);
player.load();
// after
flvjs.LoggingControl.enableDebug = true;
player.on(flvjs.Events.ERROR, (errType, errDetail) => {
    console.error('IO error:', errType, errDetail);
    // schedule reconnect here
});
Defensive patterns

Strategy: try-catch

Validate before calling

if (typeof player.on === 'function') {
    player.on(flvjs.Events.ERROR, (type, detail) => handleIoError(type, detail));
}

Try / catch

try {
    startStream();
} catch (e) {
    if (e instanceof Error && /^IOException:/.test(e.message)) {
        const msg = e.message.slice('IOException: '.length);
        scheduleReconnect(msg);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Any loader error (network disconnect, HTTP status error, exception in WebSocket/XHR loader) occurring while this._onError is null — i.e. the consumer created the IOController/transmuxer without wiring an onError callback.

Common situations: Server drops the connection mid-stream, CDN returns 403/404, WebSocket closes unexpectedly — combined with a player setup that never assigns the error handler, so the failure escapes as an uncaught runtime exception.

Related errors


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