evanw/esbuild · error · Error

Got null for source content for

Error message

Got null for source content for "${source}"

What it means

Thrown at scripts/verify-source-map.js:845. After locating an identifier in the output, the harness calls map.sourceContentFor(source) to fetch the original source text from the source map's sourcesContent. A null return means the source map does not carry embedded source content for that source, so the reverse mapping cannot be checked.

Solutions

  1. Ensure the esbuild invocation enables embedded source content (do not strip sourcesContent; avoid options that drop it).
  2. Check that the `source` path from originalPositionFor matches an entry in the map's `sources` array exactly (watch for URI-encoding/`../` differences).
  3. If content embedding is intentionally disabled, skip the sourceContentFor check in the test rather than expecting non-null.

Example fix

// before (build omits source content)
esbuild.build({ entryPoints, sourcemap: true, sourcesContent: false })

// after (embed source content so verification can read it)
esbuild.build({ entryPoints, sourcemap: true, sourcesContent: true })
Defensive patterns

Strategy: validation

Validate before calling

function hasSourceContentFor(map, source) {
  const c = map.sourceContentFor(source);
  return c !== null && c !== undefined;
}

Type guard

const hasSourceContent = (map, source) => map.sourceContentFor(source) != null;

Try / catch

try { const inCode = map.sourceContentFor(source); }
catch (e) {
  if (/Got null for source content/.test(e.message)) console.error('Source map lacks sourcesContent for', source);
  throw e;
}

Prevention

When it happens

Trigger: esbuild was run in a mode that omits sourcesContent (the generated .map has no `sourcesContent` array, or a null entry for that source). This happens when source maps are generated without embedding source text, when the source path normalization differs between `sources` and `sourcesContent`, or when an intermediate transform strips the content.

Common situations: A source-map config change disables content embedding, a bundling/chaining step drops sourcesContent, or the `source` string returned by originalPositionFor (after decodeURI) does not exactly match an entry in the sources list.

Related errors


AI-assisted analysis of evanw/esbuild@f6058f8364 (2026-08-09). Data as JSON: /api/errors/9115bfef1b2b472f. Report an issue: GitHub.

Appendix: source

Thrown at scripts/verify-source-map.js:845

      outCodeMap = await fs.readFile(path.join(tempDir, `${outfile}.map`), 'utf8')
    }

    // Check the mapping of various key locations back to the original source
    const checkMap = (out, map) => {
      for (const id in toSearch) {
        const outIndex = out.indexOf(`"${id}"`)
        if (outIndex < 0) throw new Error(`Failed to find "${id}" in output`)
        const outLines = out.slice(0, outIndex).split('\n')
        const outLine = outLines.length
        const outLastLine = outLines[outLines.length - 1]
        let outColumn = outLastLine.length
        const { source, line, column } = map.originalPositionFor({ line: outLine, column: outColumn })

        const inSource = isStdin ? '<stdin>' : toSearch[id]
        recordCheck(decodeURI(source) === inSource, `expected source: ${inSource}, observed source: ${source}`)

        const inCode = map.sourceContentFor(source)
        if (inCode === null) throw new Error(`Got null for source content for "${source}"`)
        let inIndex = inCode.indexOf(`"${id}"`)
        if (inIndex < 0) inIndex = inCode.indexOf(`'${id}'`)
        if (inIndex < 0) throw new Error(`Failed to find "${id}" in input`)
        const inLines = inCode.slice(0, inIndex).split('\n')
        const inLine = inLines.length
        const inLastLine = inLines[inLines.length - 1]
        let inColumn = inLastLine.length

        const expected = JSON.stringify({ source, line: inLine, column: inColumn })
        const observed = JSON.stringify({ source, line, column })
        recordCheck(expected === observed, `expected original position: ${expected}, observed original position: ${observed}`)

        // Also check the reverse mapping
        const positions = map.allGeneratedPositionsFor({ source, line: inLine, column: inColumn })
        recordCheck(positions.length > 0, `expected generated positions: 1, observed generated positions: ${positions.length}`)
        let found = false
        for (const { line, column } of positions) {
          if (line === outLine && column === outColumn) {

View on GitHub (pinned to f6058f8364)