clockworklabs/SpacetimeDB · error · syn::Error

must specify table accessor, e.g. `#[spacetimedb::table(acce

Error message

must specify table accessor, e.g. `#[spacetimedb::table(accessor = {table})]

What it means

Since SpacetimeDB 2.x, `#[spacetimedb::table]` requires an `accessor` argument, which names the generated accessor/row type used by module code and client bindings; `name` is optional and only sets the on-chain table name. When the attribute list contains neither an accessor nor a legacy `name`, the macro errors at call site and suggests the snake_case form of the struct ident. (Supplying only a 1.x-style `name = "..."` produces the sibling migration-hint error instead.)

Source

Thrown at crates/bindings-macro/src/table.rs:178

                // In this case, they probably intended to change `name =` to `accessor =`,
                // but were misled into keeping `name =` and changing the name from an ident into a lit string.
                // Detect that and offer a diagnostic with a simple fix.
                // Unfortunately, we can't hook in to rustc's system for providing quick fixes in compiler errors,
                // until [this ancient issue](https://github.com/rust-lang/rust/issues/54140) gets stabilized.
                let name_str_value = name_str.value();
                syn::Error::new_spanned(
                    name_str,
                    format_args!(
                        "Expected an `accessor` in table definition, but got only a `name`.
Did you mean to specify `accessor` instead?
`accessor` is required, but `name` is optional.

If you're migrating from SpacetimeDB 1.*, replace `name = {name_str_value:?}` with `accessor = {name_str_value}`",
                    ),
                )
            } else {
                let table = struct_ident.to_string().to_snake_case();
                syn::Error::new(
                    Span::call_site(),
                    format_args!("must specify table accessor, e.g. `#[spacetimedb::table(accessor = {table})]"),
                )
            }
        })?;
        Ok(TableArgs {
            access,
            scheduled,
            accessor,
            indices,
            name,
            event,
        })
    }
}

impl ScheduledArg {
    fn parse_meta(meta: ParseNestedMeta) -> syn::Result<Self> {

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Add the accessor argument: `#[spacetimedb::table(accessor = player)]` using the snake_case of the struct name
  2. When migrating from 1.x `name = "player"`, replace it with `accessor = player` (keep `name` only if you also need a distinct on-chain table name)
  3. Regenerate client bindings after the change so the accessor types line up

Example fix

// before
#[spacetimedb::table]
struct Player {
    id: u64,
}

// after
#[spacetimedb::table(accessor = player)]
struct Player {
    id: u64,
}
Defensive patterns

Strategy: validation

Validate before calling

# list table attributes lacking an accessor before building
grep -rn 'spacetimedb::table' src/ | grep -v accessor || echo OK

Prevention

When it happens

Trigger: `#[spacetimedb::table]` with an empty argument list; writing a new table after a 1.x to 2.x upgrade without adding `accessor = ...`.

Common situations: Upgrading a module from SpacetimeDB 1.x to 2.x following old tutorials or docs; creating a first table without using the 2.x project template.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/9bdf6b3875b202c7. Report an issue: GitHub.