clockworklabs/SpacetimeDB · error · TypeError
too many elements
Error message
too many elements
What it means
For a multi-column ranged index, filter()/delete() accept a prefix/range array of at most numColumns elements: all but the last are equality values and the last may be a Range bound. serializeRange throws TypeError('too many elements') when the array is longer than the index's column count: you cannot constrain more columns than the index covers.
Source
Thrown at crates/bindings-typescript/src/server/runtime.ts:1425
},
} as PointIndex<any, any>;
} else {
// numColumns != 1
const isCompleteScalarKey = (range: any[]): boolean => {
// Preserve the point-scan path only for complete scalar keys.
// A complete key with a Range in the final position is still a range
// scan over that column with equality over the preceding prefix.
return (
range.length === numColumns &&
!(range[range.length - 1] instanceof Range)
);
};
const serializeRange = (
buffer: ResizableBuffer,
range: any[]
): IndexScanArgs => {
if (range.length > numColumns) throw new TypeError('too many elements');
BINARY_WRITER.reset(buffer);
const writer = BINARY_WRITER;
const prefix_elems = range.length - 1;
for (let i = 0; i < prefix_elems; i++) {
indexSerializers[i](writer, range[i]);
}
const rstartOffset = writer.offset;
const term = range[range.length - 1];
const serializeTerm = indexSerializers[range.length - 1];
if (term instanceof Range) {
const writeBound = (bound: Bound<any>) => {
const tags = { included: 0, excluded: 1, unbounded: 2 };
writer.writeU8(tags[bound.tag]);
if (bound.tag !== 'unbounded') serializeTerm(writer, bound.value);
};
writeBound(term.from);
const rstartLen = writer.offset - rstartOffset;View on GitHub (pinned to 524b4487d9)
Solutions
- Limit the argument to at most the index's column count: filter([a, b]) or filter([a, range]) for a 2-column index
- Update every filter/delete call site for an index whenever its column list changes
- When building arrays dynamically, assert length <= index column count before calling
Example fix
// before (ranged index on [a, b]) const rows = ctx.db.t.idx.filter([a, b, someRange]); // 3 elements > 2 columns // after: equality on `a`, range over `b` const rows = ctx.db.t.idx.filter([a, someRange]);
Defensive patterns
Strategy: validation
Validate before calling
// ranged index covering N columns: at most N elements (all but last are equalities)
function assertRangeArity(range: unknown[], numColumns: number): void {
if (range.length > numColumns) {
throw new Error(`range has ${range.length} elements but index covers only ${numColumns} columns`);
}
} Prevention
- Remember the shape: equality prefix plus optionally one Range on the final indexed column, never more elements than indexed columns
- Update every filter/delete call site when an index's column list changes
- Assert dynamic array lengths before calling filter/delete in query-builder code
When it happens
Trigger: Calling filter([a, b, c]) on a two-column index; passing a full key plus a Range (numColumns + 1 elements); stale queries after a column was dropped from the index definition.
Common situations: Index narrowed from three columns to two without updating range queries; building the filter array dynamically with an off-by-one; assuming extra elements are silently ignored.
Related errors
- wrong number of elements
- Subscriptions must have at least one query
- Subscriptions must be SQL strings or typed queries
- Only btree indexes are supported in TableCacheImpl
- transaction retry failed again
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/4bd266564bc3a627.
Report an issue: GitHub.