clockworklabs/SpacetimeDB · error · TypeError

When providing a name, you must also provide the variants…

Error message

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

What it means

In SpacetimeDB 2.x, #[spacetimedb::table] requires an accessor: the snake_case identifier used for the generated module accessor and view/query traits. It is separate from name, which is optional and only sets the on-chain table name. When the argument list yields no accessor — including the 1.x-style name = "..." only form — the derive fails with a template showing the expected accessor for the struct.

Solutions

  1. Add the accessor argument with an identifier (not a string): #[spacetimedb::table(accessor = player)].
  2. Migrating from 1.x: replace name = "player" with accessor = player; keep name = "..." only if you also need a custom on-chain table name.
  3. Choose the identifier your code will reference (ctx.player, player::view(), ...).

Example fix

// before (1.x style)
#[spacetimedb::table(name = "player")]
pub struct Player { ... }

// after
#[spacetimedb::table(accessor = player)]
pub struct Player { ... }
// optional on-chain name stays separate:
#[spacetimedb::table(accessor = player, name = "player")]
Defensive patterns

Strategy: validation

Validate before calling

# CI check: 1.x-style tables without an accessor
rg -n 'spacetimedb::table\(\s*\)|spacetimedb::table\(\s*name' src/ && exit 1 || true

Prevention

When it happens

Trigger: #[spacetimedb::table] with no arguments, or #[spacetimedb::table(name = "player")] with no accessor = ... argument.

Common situations: Upgrading a 1.x module where name = "..." used to be sufficient; writing new tables from pre-2.0 docs or tutorials; renaming attributes during cleanup.

Related errors


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

Appendix: source

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

  /**
   * Creates a full sum type, where each case can have a payload.
   * Each value in the object must be a {@link TypeBuilder}.
   *
   * Example:
   * ```ts
   * t.enum("Result", { Ok: t.unit(), Err: t.string() });
   * ```
   */
  <Obj extends VariantsObj>(name: string, obj: Obj): SumBuilder<Obj>;
}

const enumImpl = ((nameOrObj: any, maybeObj?: any) => {
  let obj: any = nameOrObj;
  let name: string | undefined = undefined;

  if (typeof nameOrObj === 'string') {
    if (!maybeObj) {
      throw new TypeError(
        'When providing a name, you must also provide the variants object or array.'
      );
    }
    obj = maybeObj;
    name = nameOrObj;
  }

  // Simple sum (array form)
  if (Array.isArray(obj)) {
    const simpleVariantsObj: Record<string, UnitBuilder> = {};
    for (const variant of obj) {
      simpleVariantsObj[variant] = new UnitBuilder();
    }
    return new SimpleSumBuilderImpl(simpleVariantsObj, name);
  }

  // Regular sum (object form)
  return new SumBuilder(obj, name);

View on GitHub (pinned to 6dee26c6ef)