facebook/react · error · Error

Section offsets must be ordered and non-overlapping.

Error message

Section offsets must be ordered and non-overlapping.

What it means

The DevTools source-map consumer implements indexed source maps by binary-searching sections, which per the TC39 source-map spec requires sections to be sorted by offset and non-overlapping. When constructing the consumer it walks sections in order and throws as soon as one starts before the previous section's offset — a malformed map, not a bad lookup.

Source

Thrown at packages/react-devtools-shared/src/hooks/SourceMapConsumer.js:170

  } = {
    line: -1,
    column: 0,
  };

  const sections: Array<Section> = sourceMapJSON.sections.map(section => {
    const offset: {
      line: number,
      column: number,
      ...
    } = section.offset;
    const offsetLine0 = offset.line;
    const offsetColumn0 = offset.column;

    if (
      offsetLine0 < lastOffset.line ||
      (offsetLine0 === lastOffset.line && offsetColumn0 < lastOffset.column)
    ) {
      throw new Error('Section offsets must be ordered and non-overlapping.');
    }

    lastOffset = offset;

    return {
      offsetLine0,
      offsetColumn0,
      map: section.map,
      sourceMapConsumer: null,
    };
  });

  function originalPositionFor({
    columnNumber,
    lineNumber,
  }: SearchPosition): ResultPosition {
    // Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
    const column0 = columnNumber - 1;

View on GitHub (pinned to eafeac097b)

Solutions

  1. Regenerate the source map with a fixed/updated toolchain — ordered sections are a spec requirement, not a preference.
  2. Pre-sort sections by (line, column) offset before handing the JSON to the consumer.
  3. If the toolchain cannot guarantee order, emit a flat (non-indexed) map instead.
  4. If the map cannot be fixed, disable hook-name parsing in DevTools so the map is never consumed.

Example fix

// before
const consumer = SourceMapConsumer(sourceMapJSON);

// after — enforce the ordering the spec requires
sourceMapJSON.sections.sort((a, b) =>
  a.offset.line - b.offset.line || a.offset.column - b.offset.column,
);
const consumer = SourceMapConsumer(sourceMapJSON);
Defensive patterns

Strategy: validation

Validate before calling

function sectionsAreOrdered(sections) {
  let last = {line: -1, column: 0};
  return sections.every(section => {
    const {line, column} = section.offset;
    const ok =
      line > last.line || (line === last.line && column >= last.column);
    last = {line, column};
    return ok;
  });
}
if (sectionsAreOrdered(map.sections)) {
  const consumer = SourceMapConsumer(map);
}

Type guard

function sectionsAreOrdered(sections) {
  let last = {line: -1, column: 0};
  return sections.every(section => {
    const {line, column} = section.offset;
    const ok =
      line > last.line || (line === last.line && column >= last.column);
    last = {line, column};
    return ok;
  });
}

Try / catch

try {
  const consumer = SourceMapConsumer(sourceMapJSON);
} catch (error) {
  if (/Section offsets must be ordered/.test(error.message)) {
    sourceMapJSON.sections.sort((a, b) =>
      a.offset.line - b.offset.line || a.offset.column - b.offset.column,
    );
    consumer = SourceMapConsumer(sourceMapJSON);
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: Passing an indexed source map whose sections array is out of order or overlapping to SourceMapConsumer()/parseHookNames — e.g. produced by a concatenating bundler, a buggy sourcemap-merge plugin, an incremental build with stale sections, or a hand-edited map.

Common situations: Hook-name resolution (DevTools 'parse hook names') against apps whose toolchain emits indexed maps (concatenation, multi-pass builds); upgrading a bundler changes map emission; third-party dependencies shipping unsorted indexed maps.

Related errors


AI-assisted analysis of facebook/react@eafeac097b (2026-08-21). Data as JSON: /api/errors/493f04926cecbca3. Report an issue: GitHub.