agalwood/Motrix · warning · Error

manifest too large: ${text.length} > ${max}

Error message

manifest too large: ${text.length} > ${max}

What it means

Plain Error thrown by fetchManifest when the response body length exceeds opts.maxBytes (default 5 MiB). The guard prevents a malicious or misconfigured origin from exhausting memory by serving an arbitrarily large 'manifest' — a denial-of-service protection at the trust boundary.

Source

Thrown at src/core/media/manifest-fetcher.ts:23

  opts: {
    headers?: Record<string, string>
    fetchImpl?: typeof fetch
    maxBytes?: number
  } = {}
): Promise<string> {
  const doFetch = opts.fetchImpl ?? fetch
  const res = await doFetch(url, {
    method: 'GET',
    headers: opts.headers ?? {},
    redirect: 'follow',
  })
  if (!res.ok) {
    throw new Error(`manifest fetch failed: HTTP ${res.status}`)
  }
  const text = await res.text()
  const max = opts.maxBytes ?? DEFAULT_MAX
  if (text.length > max) {
    throw new Error(`manifest too large: ${text.length} > ${max}`)
  }
  return text
}

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Verify the URL points at a manifest (HLS .m3u8 / DASH .mpd) and not at a media file.
  2. If the manifest is legitimately large, raise opts.maxBytes to an explicit value you have reasoned about.
  3. Inspect Content-Type and Content-Length of the response before/after to confirm it is actually a manifest.
  4. If a CDN is returning a 200 HTML error page, fix the upstream routing.

Example fix

// before
const text = await fetchManifest(url, {})
// after — confirm it's a manifest and raise cap if legitimate
const text = await fetchManifest(url, {
  maxBytes: 10 * 1024 * 1024,
  headers: { Accept: 'application/vnd.apple.mpegurl, application/dash+xml' },
})
if (!/^#|<\?xml|<MPD/.test(text.trimStart())) {
  throw new Error('Response does not look like a manifest')
}
Defensive patterns

Strategy: validation

Validate before calling

function looksLikeManifest(text: string): boolean {
  return /^\s*(#|<\?xml|<MPD)/.test(text)
}
const text = await fetchManifest(url, { maxBytes: 10 * 1024 * 1024 })
if (!looksLikeManifest(text)) {
  throw new Error('Response is not a manifest (HLS/DASH). Check the URL.')
}

Type guard

function looksLikeManifest(text: string): boolean {
  return /^\s*(#EXTM3U|<\?xml|<MPD\b)/.test(text)
}

Try / catch

try {
  const text = await fetchManifest(url, { maxBytes })
} catch (e) {
  if (/manifest too large/.test(String(e))) {
    // either raise maxBytes after reasoning, or reject the URL as not-a-manifest
  } else throw e
}

Prevention

When it happens

Trigger: Calling fetchManifest against a URL whose response body is larger than the cap — e.g. an HLS master with thousands of variants, a DASH MPD that inlines SegmentTimeline with millions of <S> entries, or accidentally pointing the manifest fetcher at a media segment / large JSON endpoint.

Common situations: URL dispatch bug sending the fetcher at a media segment or full MP4 instead of the manifest; oversized live-window manifests; CDN returning an error page (large HTML) with a 200 status; legitimate large manifests that exceed the 5 MiB default.

Related errors


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