{"record":{"id":"824fb66dbe2d73d8","repo":"bilibili/flv.js","slug":"flv-onerror-onmediainfo-ontrackmetadata-ond","errorCode":null,"errorMessage":"Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified","messagePattern":"Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/demux/flv-demuxer.js","lineNumber":270,"sourceCode":"    }\n\n    _isInitialMetadataDispatched() {\n        if (this._hasAudio && this._hasVideo) {  // both audio & video\n            return this._audioInitialMetadataDispatched && this._videoInitialMetadataDispatched;\n        }\n        if (this._hasAudio && !this._hasVideo) {  // audio only\n            return this._audioInitialMetadataDispatched;\n        }\n        if (!this._hasAudio && this._hasVideo) {  // video only\n            return this._videoInitialMetadataDispatched;\n        }\n        return false;\n    }\n\n    // function parseChunks(chunk: ArrayBuffer, byteStart: number): number;\n    parseChunks(chunk, byteStart) {\n        if (!this._onError || !this._onMediaInfo || !this._onTrackMetadata || !this._onDataAvailable) {\n            throw new IllegalStateException('Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified');\n        }\n\n        let offset = 0;\n        let le = this._littleEndian;\n\n        if (byteStart === 0) {  // buffer with FLV header\n            if (chunk.byteLength > 13) {\n                let probeData = FLVDemuxer.probe(chunk);\n                offset = probeData.dataOffset;\n            } else {\n                return 0;\n            }\n        }\n\n        if (this._firstParse) {  // handle PreviousTagSize0 before Tag1\n            this._firstParse = false;\n            if (byteStart + offset !== this._dataOffset) {\n                Log.w(this.TAG, 'First time parsing but chunk byteStart invalid!');","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/bilibili/flv.js/blob/42343088f22619cf014a057b3878fe3d320016a6/src/demux/flv-demuxer.js#L252-L288","documentation":"parseChunks() requires the four consumer callbacks onError, onMediaInfo, onTrackMetadata and onDataAvailable to be registered before any FLV data is demuxed; they are the only way the demuxer delivers parsed events and errors. If any is missing, the library throws IllegalStateException up front rather than silently dropping output. It is an integration-contract check, not a data error.","triggerScenarios":"Calling flvDemuxer.parseChunks(chunk, byteStart) before assigning all four _onError/_onMediaInfo/_onTrackMetadata/_onDataAvailable callbacks (e.g. binding only some, or binding them asynchronously after the first chunk is fed).","commonSituations":"Writing a custom player pipeline around the demuxer and forgetting one callback (often onMediaInfo or onDataAvailable); wiring callbacks after starting the io loader whose onContentLengthKnown immediately drives parsing; copy-pasted demo code with some handlers removed.","solutions":["Set all four callbacks on the demuxer before the first parseChunks call","Set each property directly if using the raw demuxer: demuxer.onError = fn; demuxer.onMediaInfo = fn; demuxer.onTrackMetadata = fn; demuxer.onDataAvailable = fn","Use FlvPlayer/createPlayer instead of the raw demuxer so callbacks are wired for you"],"exampleFix":"// before\ndemuxer.onError = onError;\ndemuxer.parseChunks(chunk, 0); // throws: onMediaInfo etc. missing\n// after\ndemuxer.onError = onError;\ndemuxer.onMediaInfo = onMediaInfo;\ndemuxer.onTrackMetadata = onTrackMetadata;\ndemuxer.onDataAvailable = onDataAvailable;\ndemuxer.parseChunks(chunk, 0);","handlingStrategy":"validation","validationCode":"if (!demuxer._onError || !demuxer._onMediaInfo || !demuxer._onTrackMetadata || !demuxer._onDataAvailable) {\n  throw new Error('Register onError, onMediaInfo, onTrackMetadata and onDataAvailable before parseChunks');\n}","typeGuard":"function callbacksReady(demuxer) {\n  return [demuxer._onError, demuxer._onMediaInfo, demuxer._onTrackMetadata, demuxer._onDataAvailable]\n    .every(fn => typeof fn === 'function');\n}","tryCatchPattern":"try {\n  demuxer.parseChunks(chunk, byteStart);\n} catch (e) {\n  if (e.name === 'IllegalStateException') {\n    console.error('Demuxer callbacks not wired:', e.message);\n  } else { throw e; }\n}","preventionTips":["Wire all four callbacks immediately after constructing the demuxer, before starting any IO","Use FlvPlayer/createPlayer so callbacks are managed for you","Never assign demuxer callbacks asynchronously after data flow begins","Keep a shared setup function that initializes the full callback set"],"tags":["flv","demuxer","callback","api-contract"],"backgroundTag":"required-callback-not-registered","analyzedSha":"42343088f22619cf014a057b3878fe3d320016a6","analyzedAt":"2026-09-01T00:27:28.147Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}