bilibili/flv.js · error · RuntimeException

Fetch stream meet Early-EOF

Error message

Fetch stream meet Early-EOF

What it means

FetchStreamLoader's internal _pump loop reads the fetch body via reader.read(); when the stream ends before the expected content-length has been received, it treats it as a premature connection termination. The loader sets status to kError and fires _onError with LoaderErrors.EARLY_EOF (code -1), or throws a RuntimeException if no error callback was registered. This means the server (or a proxy) closed the connection mid-download.

Source

Thrown at src/io/fetch-stream-loader.js:199

                    this._abortController.abort();
                } catch (e) {}
            }
        }
    }

    _pump(reader) {  // ReadableStreamReader
        return reader.read().then((result) => {
            if (result.done) {
                // First check received length
                if (this._contentLength !== null && this._receivedLength < this._contentLength) {
                    // Report Early-EOF
                    this._status = LoaderStatus.kError;
                    let type = LoaderErrors.EARLY_EOF;
                    let info = {code: -1, msg: 'Fetch stream meet Early-EOF'};
                    if (this._onError) {
                        this._onError(type, info);
                    } else {
                        throw new RuntimeException(info.msg);
                    }
                } else {
                    // OK. Download complete
                    this._status = LoaderStatus.kComplete;
                    if (this._onComplete) {
                        this._onComplete(this._range.from, this._range.from + this._receivedLength - 1);
                    }
                }
            } else {
                if (this._abortController && this._abortController.signal.aborted) {
                    this._status = LoaderStatus.kComplete;
                    return;
                } else if (this._requestAbort === true) {
                    this._status = LoaderStatus.kComplete;
                    return reader.cancel();
                }

                this._status = LoaderStatus.kBuffering;

View on GitHub (pinned to 42343088f2)

Solutions

  1. Add an onError handler to the loader (or listen for the player's LOAD_ERROR/NetworkError) and implement a retry that re-opens the stream from the last received byte offset using a Range request
  2. Verify no intermediary (proxy/CDN/load balancer) has an idle/timeout limit shorter than the download duration and raise it
  3. Confirm the server sends a correct Content-Length or use chunked transfer encoding consistently
  4. Switch loader type (e.g. to RangeLoader/XHR-based loader) via config for flaky networks

Example fix

// before
loader.create(url, { from: 0, to: -1 }); // no error handling; throws RuntimeException
// after
loader._onError = (type, info) => {
  if (type === LoaderErrors.EARLY_EOF) {
    // resume from last received offset with a Range request
    loader.create(url, { from: loader._receivedLength, to: -1 });
  }
};
loader.create(url, { from: 0, to: -1 });
Defensive patterns

Strategy: retry

Validate before calling

const res = await fetch(url);
if (!res.ok || !res.body) throw new Error('bad response');
const len = Number(res.headers.get('content-length'));
if (Number.isNaN(len)) console.warn('no content-length; EOF detection limited');

Try / catch

loader._onError = (type, info) => {
  if (type === LoaderErrors.EARLY_EOF) {
    setTimeout(() => loader.create(url, { from: lastReceivedOffset, to: -1 }), backoffMs);
  }
};

Prevention

When it happens

Trigger: Calling create() on a FetchStreamLoader and, during streaming, the response body ReadableStream ends while _receivedLength < _contentLength; typically response.headers content-length was advertised but the connection dropped before that many bytes arrived. Also raised when res.body is null/unreadable mid-pump or the reader's done flag arrives early.

Common situations: Unstable mobile networks, proxy/CDN idle timeouts (nginx, Cloudflare) cutting long streaming responses, server crashes or restarts mid-transfer, load balancers killing slow connections, or servers that send an incorrect Content-Length header.

Related errors


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