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
- 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).
- Inspect data.msg in the thrown message to identify the root cause (network vs HTTP status).
- 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
- Always register the ERROR event / onError callback immediately after creating the player or loader.
- Never leave this._onError unset on IOController-backed pipelines.
- Log errType/errDetail centrally to distinguish network vs media errors.
- Implement bounded exponential-backoff reconnect for transient IO failures.
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
- MozChunkedLoader: Http code invalid, ' + xhr.status + ' ' +
- MSStreamLoader: Http code invalid, ' + xhr.status + ' ' + xh
- RangeLoader: Http code invalid, ' + xhr.status + ' ' + xhr.s
- FetchStreamLoader: Http code invalid, ' + res.status + ' ' +
- Fetch stream meet Early-EOF
AI-assisted analysis of bilibili/flv.js@42343088f2 (2026-09-01).
Data as JSON: /api/errors/025fe52c455b57af.
Report an issue: GitHub.