clockworklabs/SpacetimeDB · error

unexpected error from `datastore_index_scan_range_bsatn`: {e

Error message

unexpected error from `datastore_index_scan_range_bsatn`: {e}

What it means

Raised inside a SpacetimeDB reducer when `datastore_index_scan_range_bsatn` — the syscall backing ranged index reads — fails unexpectedly. It fires from the shared `filter` helper used by both `RangedIndex::filter` and the read-only `RangedIndexReadOnly::filter` on view handles. The bindings treat every non-OK errno from a range scan as a bug or an environment mismatch, so this panic indicates host/module disagreement or a host error, not bad range syntax (type errors are caught at compile time).

Source

Thrown at crates/bindings/src/table.rs:991

/// Performs a ranged scan using the range arguments `B` in `Tbl` using `Idx`.
///
/// The type parameter `K` is either `()` or [`SingleBound`]
/// and is used to workaround the orphan rule.
fn filter<Tbl, Idx, IndexType, B, K>(b: B) -> impl Iterator<Item = Tbl::Row>
where
    Tbl: Table,
    Idx: Index,
    B: IndexScanRangeBounds<IndexType, K>,
{
    let index_id = Idx::index_id();

    let iter = if const { is_point_scan::<Idx, B, _, _>() } {
        b.with_point_arg(|point| datastore_index_scan_point_bsatn(index_id, point))
    } else {
        let args = b.get_range_args();
        let (prefix, prefix_elems, rstart, rend) = args.args_for_syscall();
        sys::datastore_index_scan_range_bsatn(index_id, prefix, prefix_elems, rstart, rend)
            .unwrap_or_else(|e| panic!("unexpected error from `datastore_index_scan_range_bsatn`: {e}"))
    };

    TableIter::new(iter)
}

/// A read-only handle to a B-tree or Direct index.
///
/// This is the read-only version of [`RangedIndex`].
/// It mirrors [`RangedIndex`] but exposes only `.filter(..)`, not `.delete(..)`.
/// It is used by `{table}__ViewHandle` to keep view code read-only at compile time.
///
/// Note, the `Tbl` generic is the read-write table handle `{table}__TableHandle`.
/// This is because read-only indexes still need [`Table`] metadata.
/// The view handle itself deliberately does not implement `Table`.
pub struct RangedIndexReadOnly<Tbl: Table, IndexType, Idx: Index> {
    _marker: PhantomData<(Tbl, IndexType, Idx)>,
}

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Republish the module against the current database so index definitions match: `spacetime publish <db>`; if schema evolution is involved, publish to a fresh database to confirm.
  2. Pin matching versions of `spacetimedb-bindings` and the spacetimedb server/CLI you run.
  3. Narrow the range (or split it into batches) to rule out oversized scans stressing the host.
  4. Persist the errno `{e}` from the panic and file an issue with SpacetimeDB if versions already match — the code path considers this state unreachable.
Defensive patterns

Strategy: validation

Try / catch

let scan = std::panic::catch_unwind(|| {
    ctx.db.user().dogs_and_name().filter(25u64..).collect::<Vec<_>>()
});
match scan {
    Ok(rows) => { /* use rows */ }
    Err(panic) => { log::error!("index scan failed: {panic:?}"); return Err("internal scan failure".into()); }
}

Prevention

When it happens

Trigger: Iterating an index with a non-point range, e.g. `ctx.db.user().dogs_and_name().filter(25u64..)` or `filter((25u64, "J".."K"))`, when the host cannot perform the scan: module schema out of sync with the database, bindings/server version mismatch, or resource exhaustion inside the host while opening the row iterator.

Common situations: Reading from a `{table}__ViewHandle` inside view code after the underlying table's index changed without republish; long-running servers upgraded independently of deployed modules; integration tests hitting a host bug.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/7999e6187b220a0a. Report an issue: GitHub.