agalwood/Motrix · error · HttpError

plugin.http.response_too_large

plugin.http.response_too_large

Error message

Response body exceeded ${maxBodyBytes} bytes

What it means

While streaming the response body, accumulated bytes exceeded maxBodyBytes (default 50 MB, hard ceiling 200 MB). The internal controller is aborted with reason 'body_too_large', the body stream is destroyed, and after read-loop cleanup the capped flag triggers this error. This prevents a single response from exhausting plugin memory.

Source

Thrown at src/core/plugin/capabilities/http.ts:514

  try {
    for await (const chunk of response.body) {
      const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
      totalBytes += buf.byteLength
      if (totalBytes > maxBodyBytes) {
        capped = true
        internalCtrl.abort('body_too_large')
        response.body.destroy?.()
        break
      }
      chunks.push(buf)
    }
  } catch {
    // Ignore stream errors that arise from aborting the body read.
  }
  doCleanup()

  if (capped) {
    throw new HttpError(
      'plugin.http.response_too_large',
      `Response body exceeded ${maxBodyBytes} bytes`
    )
  }

  const rawBody = Buffer.concat(chunks)
  let parsedBody: unknown
  if (responseType === 'bytes') {
    parsedBody = new Uint8Array(
      rawBody.buffer,
      rawBody.byteOffset,
      rawBody.byteLength
    )
  } else if (responseType === 'json') {
    parsedBody = JSON.parse(rawBody.toString('utf8'))
  } else {
    parsedBody = rawBody.toString('utf8')
  }

View on GitHub (pinned to 1a708ee577)

Solutions

  1. If the payload is legitimate, raise opts.maxBodyBytes up to the 200 MB hard ceiling.
  2. Stream large artifacts to disk via fs rather than loading into memory via http.
  3. Inspect Content-Length before reading the body and bail early.
  4. Narrow the request (pagination, field selection, range headers) to reduce payload size.

Example fix

// before
await http.request({ url: bigFileUrl, responseType: 'bytes' })

// after
await http.request({ url: bigFileUrl, responseType: 'bytes', maxBodyBytes: 200 * 1024 * 1024 })
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight via HEAD to learn size, before paying for the body
const head = await http.request({ url, method: 'HEAD', responseType: 'text' })
const len = Number(head.headers['content-length'] ?? 0)
if (len && len > maxAllowed) throw new Error('too large; refusing to download')

Try / catch

try {
  return await http.request({ ...opts, maxBodyBytes: 200 * 1024 * 1024 })
} catch (e) {
  if (e instanceof HttpError && e.code === 'plugin.http.response_too_large') {
    // switch to streaming-to-disk path instead of buffering
  } else throw e
}

Prevention

When it happens

Trigger: Downloading a large file; an API that returns an unbounded result set; a server streaming a log/dump; a malicious or misconfigured endpoint returning megabytes of data; opts.maxBodyBytes set lower than the legitimate payload.

Common situations: Default 50 MB too small for legitimate media downloads; plugin does not pre-check Content-Length; paginated API that ignores limit params.

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/10b5c2031112f912. Report an issue: GitHub.