avajs/ava · error · RangeError
Cannot record snapshot ${index} for ${JSON.stringify(belongs
Error message
Cannot record snapshot ${index} for ${JSON.stringify(belongsTo)}, exceeds expected index of ${snapshots.length} What it means
During recording, AVA appends snapshots to a per-title block in order. recordSerialized() throws a RangeError when a snapshot's index is greater than the number of snapshots already collected for that belongsTo key, meaning the test reported snapshots out of order or skipped one, so the serialized output would have a gap.
Source
Thrown at lib/snapshot-manager.js:327
}
this.record(options);
return {pass: true};
}
const actual = concordance.deserialize(Buffer.from(data.buffer, data.byteOffset, data.byteLength), concordanceOptions);
const expected = concordance.describe(options.expected, concordanceOptions);
const pass = concordance.compareDescriptors(actual, expected);
return {actual, expected, pass};
}
recordSerialized({data, label, belongsTo, index}) {
const block = this.newBlocksByTitle.get(belongsTo) ?? {snapshots: []};
const {snapshots} = block;
if (index > snapshots.length) {
throw new RangeError(`Cannot record snapshot ${index} for ${JSON.stringify(belongsTo)}, exceeds expected index of ${snapshots.length}`);
} else if (index < snapshots.length) {
if (snapshots[index].data) {
throw new RangeError(`Cannot record snapshot ${index} for ${JSON.stringify(belongsTo)}, already exists`);
}
snapshots[index] = {data, label};
} else {
snapshots.push({data, label});
}
this.newBlocksByTitle.set(belongsTo, block);
}
deferRecord(options) {
const {expected, belongsTo, label, index} = options;
const descriptor = concordance.describe(expected, concordanceOptions);
const buffer = concordance.serialize(descriptor);
const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);View on GitHub (pinned to bbfd946322)
Solutions
- Fix the source so snapshot records are emitted in ascending index order with no gaps for each belongsTo group
- Make snapshot assertions unconditional or ensure a failed assertion still records its snapshot (use deferRecord) so indices stay contiguous
- If using a custom reporter/plugin, buffer records and flush them sorted by index before calling recordSerialized
Example fix
// before (custom reporter, async out of order) records.forEach(r => recordSerialized(r)); // after records.sort((a, b) => a.index - b.index).forEach(r => recordSerialized(r));
Defensive patterns
Strategy: try-catch
Validate before calling
if (index > snapshots.length) {
throw new Error(`pre-check: snapshot index ${index} would leave a gap (expected ${snapshots.length})`);
} Type guard
function canRecordAt(block, index) {
return Number.isInteger(index) && index >= 0 && index <= block.snapshots.length;
} Try / catch
try {
recordSerialized({data, label, belongsTo, index});
} catch (err) {
if (err instanceof RangeError && /exceeds expected index/.test(err.message)) {
// emit records in ascending order; re-run with records sorted by index
} else { throw err; }
} Prevention
- Ensure snapshot records are emitted synchronously and in ascending index order per belongsTo group
- In custom reporters, sort pending records by index before flushing
- Keep snapshot assertions unconditional so skipped assertions do not create index gaps
When it happens
Trigger: Calling recordSerialized (via deferRecord/skipSnapshot) with an index jumping ahead of snapshots.length for the same belongsTo group — e.g. a reporter/plugin emitting snapshot records out of sequence, or a test asserting snapshots non-deterministically so one index is skipped.
Common situations: Custom AVA reporters or integrations emitting snapshot records concurrently/out of order; failing tests that skip recording one snapshot while later ones still record; flaky tests with conditional snapshot assertions.
Related errors
AI-assisted analysis of avajs/ava@bbfd946322 (2026-09-02).
Data as JSON: /api/errors/5268c6a5ead573e3.
Report an issue: GitHub.