clockworklabs/SpacetimeDB · error
unique: unexpected error from datastore_delete_by_index_scan
Error message
unique: unexpected error from datastore_delete_by_index_scan_point_bsatn: {e} What it means
UniqueColumn::delete deletes the row whose unique-column value matches, returning false when no such row exists (normal miss, not an error). The panic fires only when the underlying datastore_delete_by_index_scan_point_bsatn syscall itself returns an error - e.g. the BSATN-encoded key point fails to decode against the index's key type or the index id is invalid for the deployed schema.
Source
Thrown at crates/bindings/src/table.rs:372
{
find::<Tbl, Col>(col_val.borrow())
}
/// Deletes the row where the value in the unique column matches the supplied `col_val`,
/// if any such row is present in the database state.
///
/// Returns `true` if a row with the specified `col_val` was previously present and has been deleted,
/// or `false` if no such row was present.
#[inline]
pub fn delete(&self, col_val: impl Borrow<Col::ColType>) -> bool {
self._delete(col_val.borrow()).0
}
fn _delete(&self, col_val: &Col::ColType) -> (bool, IterBuf) {
let index_id = Col::index_id();
let point = IterBuf::serialize(col_val).unwrap();
let n_del = sys::datastore_delete_by_index_scan_point_bsatn(index_id, &point).unwrap_or_else(|e| {
panic!("unique: unexpected error from datastore_delete_by_index_scan_point_bsatn: {e}")
});
(n_del > 0, point)
}
/// Deletes the row where the value in the unique column matches that in the corresponding field of `new_row`, and
/// then inserts the `new_row`.
///
/// Returns the new row as actually inserted, with computed values substituted for any auto-inc placeholders.
///
/// This method can only be called on primary key columns, not any unique column.
/// This prevents confusion regarding what constitutes a row update vs. a delete+insert.
/// To perform this operation for a non-primary unique column, call
/// `.delete(key)` followed by `.insert(row)`.
///
/// # Panics
/// Panics if no row was previously present with the matching value in the unique column,
/// or if either the delete or the insertion would violate a constraint.View on GitHub (pinned to 6dee26c6ef)
Solutions
- Verify the column is actually #[unique] (this API is for unique columns) and that bindings are freshly generated.
- Clean rebuild and republish (cargo clean && spacetime publish) so index ids match the deployed schema.
- Align the spacetimedb crate version with the host server version; if it still reproduces, file an issue with the errno.
Defensive patterns
Strategy: validation
Prevention
- Confirm the column is #[unique] before using its delete-by-value API.
- Regenerate bindings and republish together after any schema change.
- Keep spacetimedb crate and server versions aligned.
When it happens
Trigger: Module/host schema skew: bindings compiled against an index definition that differs from the deployed one; a column type change (e.g. u32 to u64) so the serialized point no longer matches the index key's AlgebraicType; stale index ids after republishing without a matching rebuild.
Common situations: Redeploying a module with column type changes while the crate and host versions drift; using hand-modified generated table code with wrong index ids.
Related errors
- unexpected error from `datastore_delete_by_index_scan_point_
- Failed to get table with name: {table_name}
- {e}
- unexpected error from `datastore_index_scan_point_bsatn`: {e
- Delete for non-existent row when replaying transaction
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/743d1b4deec5e86f.
Report an issue: GitHub.