{"record":{"id":"025fe52c455b57af","repo":"bilibili/flv.js","slug":"ioexception-data-msg","errorCode":null,"errorMessage":"IOException: ' + data.msg","messagePattern":"IOException: ' \\+ data\\.msg","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"src/io/io-controller.js","lineNumber":641,"sourceCode":"                        return;\n                    }\n                    // else: We don't know totalLength, throw UnrecoverableEarlyEof\n                }\n                // live stream: throw UnrecoverableEarlyEof error to upper-layer\n                type = LoaderErrors.UNRECOVERABLE_EARLY_EOF;\n                break;\n            }\n            case LoaderErrors.UNRECOVERABLE_EARLY_EOF:\n            case LoaderErrors.CONNECTING_TIMEOUT:\n            case LoaderErrors.HTTP_STATUS_CODE_INVALID:\n            case LoaderErrors.EXCEPTION:\n                break;\n        }\n\n        if (this._onError) {\n            this._onError(type, data);\n        } else {\n            throw new RuntimeException('IOException: ' + data.msg);\n        }\n    }\n\n}\n\nexport default IOController;","sourceCodeStart":623,"sourceCodeEnd":647,"githubUrl":"https://github.com/bilibili/flv.js/blob/42343088f22619cf014a057b3878fe3d320016a6/src/io/io-controller.js#L623-L647","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst player = flvjs.createPlayer(mediaDataSource);\nplayer.attachMediaElement(video);\nplayer.load();\n// after\nflvjs.LoggingControl.enableDebug = true;\nplayer.on(flvjs.Events.ERROR, (errType, errDetail) => {\n    console.error('IO error:', errType, errDetail);\n    // schedule reconnect here\n});","handlingStrategy":"try-catch","validationCode":"if (typeof player.on === 'function') {\n    player.on(flvjs.Events.ERROR, (type, detail) => handleIoError(type, detail));\n}","typeGuard":null,"tryCatchPattern":"try {\n    startStream();\n} catch (e) {\n    if (e instanceof Error && /^IOException:/.test(e.message)) {\n        const msg = e.message.slice('IOException: '.length);\n        scheduleReconnect(msg);\n    } else {\n        throw e;\n    }\n}","preventionTips":["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."],"tags":["network","io","missing-callback","loader"],"backgroundTag":"io-loader-error","analyzedSha":"42343088f22619cf014a057b3878fe3d320016a6","analyzedAt":"2026-09-01T00:27:28.147Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}