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
- Add the accessor argument: `#[spacetimedb::table(accessor = player)]` using the snake_case of the struct name
- 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)
- 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
- Write `accessor = <snake_case_name>` by habit when creating every table
- After a SpacetimeDB version upgrade, grep for `spacetimedb::table(name =` and migrate each hit
- Copy table declarations from current docs or the project template, not from old projects
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
- spacetimedb table must be a struct
- unions not supported
- a direct index must be paired with a `#[unique] constraint
- not a column of the table
- invalid combination: auto_inc, unique index or primary key c
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/9bdf6b3875b202c7.
Report an issue: GitHub.