vercel/next.js · error

[inspect] ${route}: document contains __next_f but the extra

Error message

[inspect] ${route}: document contains __next_f but the extraction regex matched no inline Flight scripts — the markup shape changed, update the regex in inspectRouteDocument

What it means

Thrown by inspectRouteDocument (benchmark.ts:436) when the document HTML contains the literal '__next_f' (so it looks like an App Router document) but the flight-script extraction regex /<script[^>]*>(self\.__next_f\.push\(.*?)<\/script>/gs matched zero scripts. The guard exists because a silent zero would corrupt the inlineFlightShare metric; if the markup shape changed (e.g. Flight scripts now use a different tag/attribute/nonce scheme, or __next_f is referenced in non-script context), the regex must be updated rather than reporting wrong numbers.

Source

Thrown at bench/render-pipeline/benchmark.ts:436

    if (!response.ok) {
      throw new Error(`Request failed (${response.status}) for ${url}`)
    }
    const bytes = Buffer.byteLength(text)
    const gzipBytes = zlib.gzipSync(text).byteLength
    let inlineFlightBytes = 0
    let inlineFlightScripts = 0
    // Inline Flight scripts can carry attributes (e.g. a CSP nonce), so
    // match any <script ...> tag; the content anchor identifies them.
    const flightScript = /<script[^>]*>(self\.__next_f\.push\(.*?)<\/script>/gs
    for (const match of text.matchAll(flightScript)) {
      inlineFlightBytes += Buffer.byteLength(match[1])
      inlineFlightScripts++
    }
    if (inlineFlightScripts === 0) {
      // Every App Router document carries inline Flight scripts; a
      // silent zero would corrupt the flight-share metric.
      if (text.includes('__next_f')) {
        throw new Error(
          `[inspect] ${route}: document contains __next_f but the extraction regex matched no inline Flight scripts — the markup shape changed, update the regex in inspectRouteDocument`
        )
      }
      throw new Error(
        `[inspect] ${route}: not an App Router document (no __next_f) — this benchmark only measures App Router routes`
      )
    }
    return {
      route,
      bytes,
      gzipBytes,
      inlineFlightBytes,
      inlineFlightShare: bytes > 0 ? inlineFlightBytes / bytes : 0,
      inlineFlightScripts,
    }
  } finally {
    clearTimeout(timeout)
  }

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Inspect the actual document HTML (curl the route, grep for __next_f) to see the new tag shape.
  2. Update the flightScript regex in inspectRouteDocument (line 427) to match the current markup — e.g. account for new attributes, self-closing variations, or a changed payload delimiter.
  3. Add a fixture test for the regex against a real current document so this breaks loudly in CI next time.
  4. Confirm you're not pointing the benchmark at a non-App-Router route (that case is the separate error at line 440).

Example fix

// before
const flightScript = /<script[^>]*>(self\.__next_f\.push\(.*?)<\/script>/gs

// after — example: the new markup wraps the script with a nonce AND the push
// argument is now quoted differently; loosen the tag head and anchor on the push call
const flightScript =
  /<script\b[^>]*>([\s\S]*?self\.__next_f\.push\([\s\S]*?<\/script>/g
// (adjust to the actual current shape after inspecting the document)
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check the extraction regex against a current document before relying on it:
function countFlightScripts(html: string): number {
  const re = /<script[^>]*>(self\.__next_f\.push\(.*?)<\/script>/gs
  let n = 0
  while (re.exec(html)) n++
  return n
}
// in a test: assert countFlightScripts(realCurrentDocument) > 0

Type guard

function isFlightRegexStaleError(err: unknown): boolean {
  return err instanceof Error && /extraction regex matched no inline Flight scripts/.test(err.message)
}

Try / catch

// This is a tooling bug, not a runtime blip — don't silently swallow it.
try {
  await inspectRouteDocument(url, route, timeoutMs)
} catch (err) {
  if (isFlightRegexStaleError(err)) {
    console.error('Flight script markup changed. Curl the route, grep __next_f, and update the regex in inspectRouteDocument.')
  }
  throw err
}

Prevention

When it happens

Trigger: A Next.js version change alters how inline Flight scripts are emitted: the script tag gains an attribute pattern the regex's [^>]* no longer spans, the push payload format changes, or __next_f appears outside a <script> (e.g. in a data attribute or JSON blob). The check at line 435 (`text.includes('__next_f')`) passes but the matchAll at 428 yields nothing, so line 432-438 fires.

Common situations: Upgrading Next.js changes the inline Flight script markup; a CSP nonce or type attribute now wraps the script in a way the regex mishandles; the document references __next_f in a <script type='application/json'> or a data island the regex excludes; Turbopack vs webpack emit differing shapes.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/12876cec29af5550. Report an issue: GitHub.