vitest-dev/vitest · error · Error

offset is longer than source length! offset ${offset} > leng

Error message

offset is longer than source length! offset ${offset} > length ${source.length}

What it means

Thrown by offsetToLineNumber() in packages/utils/src/offset.ts when the requested character offset exceeds the source string length. offsetToLineNumber is used to map a character index back to a 1-based line number for diagnostics, inline snapshot placement, and stack-trace rendering. An out-of-range offset means the caller computed the offset against a different (longer) version of the source than the one passed in — typically a stale cache or a transform mismatch.

Source

Thrown at packages/utils/src/offset.ts:25

): number {
  const lines = source.split(lineSplitRE)
  const nl = /\r\n/.test(source) ? 2 : 1
  let start = 0

  if (lineNumber > lines.length) {
    return source.length
  }

  for (let i = 0; i < lineNumber - 1; i++) {
    start += lines[i].length + nl
  }

  return start + columnNumber
}

export function offsetToLineNumber(source: string, offset: number): number {
  if (offset > source.length) {
    throw new Error(
      `offset is longer than source length! offset ${offset} > length ${source.length}`,
    )
  }
  const lines = source.split(lineSplitRE)
  const nl = /\r\n/.test(source) ? 2 : 1
  let counted = 0
  let line = 0
  for (; line < lines.length; line++) {
    const lineLength = lines[line].length + nl
    if (counted + lineLength >= offset) {
      break
    }

    counted += lineLength
  }
  return line + 1
}

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Clear Vitest/Vite caches (rm -rf node_modules/.vite node_modules/.vitest) and re-run.
  2. Ensure the source string passed to offsetToLineNumber is the same artifact used to compute the offset.
  3. If implementing a custom SnapshotEnvironment or transformer, guarantee readSnapshotFile returns stable content.
  4. Update @vitest/utils and vitest to matching versions; mismatched versions across the monorepo cause this.
Defensive patterns

Strategy: validation

Validate before calling

function assertOffsetInRange(source: string, offset: number): void {
  if (offset > source.length) {
    throw new RangeError(`offset ${offset} exceeds source length ${source.length}`)
  }
}

Type guard

const offsetInRange = (source: string, offset: number): boolean =>
  offset >= 0 && offset <= source.length

Prevention

When it happens

Trigger: Source-map or inline-snapshot code computes an offset from the transformed code but passes the original (shorter) source; a custom SnapshotEnvironment returns a different file content on consecutive reads; instrumentation that mutates the source between offset calculation and line lookup.

Common situations: Source-map mismatches after a Vite/Rollup upgrade; cache invalidation issues (.vite cache stale); concurrent edits during watch mode; custom transformers that change file length without updating the source map.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/90e63c16be911a45.json. Report an issue: GitHub.