clockworklabs/SpacetimeDB · error · TypeError

When providing a name, you must also provide the object.

Error message

When providing a name, you must also provide the object.

What it means

When validating index arguments in #[spacetimedb::table(index(...))], the macro requires a Direct index column to carry #[unique]. A direct index maps each column value to at most one row, which is only sound for unique columns, so the combination without #[unique] is rejected at derive time.

Solutions

  1. Add #[unique] to the same column if values are guaranteed distinct.
  2. If duplicate values must be allowed, use #[index(btree)] or #[index(hash)] instead — they index many rows per key.
  3. Verify #[unique] sits on the column (field attribute), not on the table.

Example fix

// before
#[spacetimedb::table(index(direct = email))]
pub struct User { #[auto_inc] pub id: u64, pub email: String }

// after
#[spacetimedb::table(index(direct = email))]
pub struct User {
    #[auto_inc] pub id: u64,
    #[unique] pub email: String,   // direct index requires unique
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Declaring a direct index on a column that is not marked #[unique], e.g. a table with #[index(direct)] (or the direct index form naming that column) but no #[unique] attribute on the field.

Common situations: Adding 'direct' for fast point lookups without realizing it implies uniqueness; removing #[unique] during a refactor while keeping the direct index.

Related errors


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

Appendix: source

Thrown at crates/bindings-typescript/src/lib/type_builders.ts:3913

   * @returns A new {@link F64Builder} instance
   */
  f64: (): F64Builder => new F64Builder(),

  /**
   * Creates a new `Product` {@link AlgebraicType} to be used in table definitions. Product types in SpacetimeDB
   * are essentially the same as objects in JavaScript/TypeScript.
   * Properties of the object must also be {@link TypeBuilder}s.
   * Represented as an object with specific properties in TypeScript.
   *
   * @param name (optional) A display name for the product type. If omitted, an anonymous product type is created.
   * @param obj The object defining the properties of the type, whose property
   * values must be {@link TypeBuilder}s.
   * @returns A new {@link ProductBuilder} instance.
   */
  object: ((nameOrObj: any, maybeObj?: any) => {
    if (typeof nameOrObj === 'string') {
      if (!maybeObj) {
        throw new TypeError(
          'When providing a name, you must also provide the object.'
        );
      }
      return new ProductBuilder(maybeObj, nameOrObj);
    }
    return new ProductBuilder(nameOrObj, undefined);
  }) as {
    <Obj extends ElementsObj>(name: string, obj: Obj): ProductBuilder<Obj>;
    // TODO: Currently names are not optional
    // <Obj extends ElementsObj>(obj: Obj): ProductBuilder<Obj>;
  },

  /**
   * Creates a new `Row` {@link AlgebraicType} to be used in table definitions. Row types in SpacetimeDB
   * are similar to `Product` types, but are specifically used to define the schema of a table row.
   * Properties of the object must also be {@link TypeBuilder} or {@link ColumnBuilder}s.
   *
   * You can represent a `Row` as either a {@link RowObj} or an {@link RowBuilder} type when

View on GitHub (pinned to 6dee26c6ef)