clockworklabs/SpacetimeDB · error

{e}

Error message

{e}

What it means

TableHandle::insert panics with the error returned by try_insert: a UniqueConstraintViolation when the row's unique-column or primary-key value is already present on a different row, or an AutoIncOverflow when an auto-increment column exhausted its type. Exact duplicates are no-ops (set semantics) - the panic is specifically a different row reusing a unique value.

Source

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

    ///
    /// The return value is the inserted row, with any auto-incrementing columns replaced with computed values.
    /// The `insert` method always returns the inserted row,
    /// even when the table contains no auto-incrementing columns.
    ///
    /// (The returned row is a copy of the row in the database.
    /// Modifying this copy does not directly modify the database.
    /// See [`UniqueColumn::update`] if you want to update the row.)
    ///
    /// May panic if inserting the row violates any constraints.
    /// Callers which intend to handle constraint violation errors should instead use [`Self::try_insert`].
    ///
    /// Inserting an exact duplicate of a row already present in the table is a no-op,
    /// as SpacetimeDB is a set-semantic database.
    /// This is true even for tables with unique constraints;
    /// inserting an exact duplicate of an already-present row will not panic.
    #[track_caller]
    fn insert(&self, row: Self::Row) -> Self::Row {
        self.try_insert(row).unwrap_or_else(|e| panic!("{e}"))
    }

    /// The error type for this table for unique constraint violations. Will either be
    /// [`UniqueConstraintViolation`] if the table has any unique constraints, or [`Infallible`]
    /// otherwise.
    type UniqueConstraintViolation: MaybeError<UniqueConstraintViolation>;

    /// The error type for this table for auto-increment overflows. Will either be
    /// [`AutoIncOverflow`] if the table has any auto-incrementing columns, or [`Infallible`]
    /// otherwise.
    type AutoIncOverflow: MaybeError<AutoIncOverflow>;

    /// Counterpart to [`Self::insert`] which allows handling failed insertions.
    ///
    /// For tables with constraints, this method returns an `Err` when the insertion fails rather than panicking.
    /// For tables without any constraints, [`Self::UniqueConstraintViolation`] and [`Self::AutoIncOverflow`]
    /// will be [`std::convert::Infallible`], and this will be a more-verbose [`Self::insert`].
    ///

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Switch to try_insert and handle the Err(UniqueConstraintViolation) branch for expected duplicates.
  2. If upsert is intended, use the primary key column's insert_or_update / update APIs instead of insert.
  3. Pre-check existence via the unique column handle (ctx.db.my_table().id().find(value)) before inserting.

Example fix

// before: panics when a user with this email already exists
ctx.db.user().insert(User { email, name });

// after: handle the violation explicitly
if let Err(_e) = ctx.db.user().try_insert(User { email, name }) {
    // unique constraint violated - update instead, or return an error to the client
}
// or, on a primary key column: ctx.db.user().id().insert_or_update(row);
Defensive patterns

Strategy: try-catch

Validate before calling

let existing = ctx.db.user().email().find(&row.email);
if existing.is_some() {
    // duplicate unique value - update instead of insert
}

Try / catch

match ctx.db.user().try_insert(row) {
    Ok(inserted) => inserted,
    Err(err) => {
        // UniqueConstraintViolation or AutoIncOverflow
        Err(reject(format!("duplicate: {err}")))
    }
}

Prevention

When it happens

Trigger: Inserting a second row with the same #[unique]#[primary_key] value but different other fields; seeding logic running twice with fresh non-key fields; auto-inc i64 column that overflowed after ~9.2e18 inserts.

Common situations: Seed reducers re-run on every publish; two concurrent reducer calls inserting the same key (one transaction aborts with this panic); expecting upsert semantics from insert.

Related errors


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