clockworklabs/SpacetimeDB · error · syn::Error

must specify view accessor, e.g. `#[spacetimedb::view(access

Error message

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

What it means

SpacetimeDB views must declare `accessor = ...`, which names the generated view accessor used by module code and clients. When the attribute parses without an accessor, the macro errors at call site and suggests the snake_case of the view function's ident. Like tables in 2.x, views migrated from older versions need this argument added.

Source

Thrown at crates/bindings-macro/src/view.rs:83

                sym::public => {
                    check_duplicate_msg(&public, &meta, "`public` already specified")?;
                    public = Some(());
                }
                sym::accessor => {
                    check_duplicate_msg(&accessor, &meta, "`accessor` already specified")?;
                    accessor = Some(meta.value()?.parse()?);
                }
                sym::primary_key => {
                    check_duplicate_msg(&primary_key, &meta, "`primary_key` already specified")?;
                    primary_key = Some(ViewPrimaryKeyArg::parse(meta.value()?)?);
                }
            });
            Ok(())
        })
        .parse2(input)?;
        let accessor = accessor.ok_or_else(|| {
            let view = func_ident.to_string().to_snake_case();
            syn::Error::new(
                Span::call_site(),
                format_args!("must specify view accessor, e.g. `#[spacetimedb::view(accessor = {view})]"),
            )
        })?;
        let () = public
            .ok_or_else(|| syn::Error::new(Span::call_site(), "views must be `public`, e.g. `#[view(public)]`"))?;
        Ok(Self {
            name,
            primary_key,
            public: true,
            accessor,
        })
    }
}

/// If `ty` is `impl Query<T>`, returns `Some(T)`. Otherwise `None`.
fn extract_impl_query_inner(ty: &syn::Type) -> Option<&syn::Type> {
    if let syn::Type::ImplTrait(impl_trait) = ty {

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Add the accessor: `#[spacetimedb::view(accessor = top_scores)]` using the snake_case of the fn name
  2. Add `public` while you are there — it is also mandatory
  3. Regenerate bindings after the change so clients pick up the view accessor

Example fix

// before
#[spacetimedb::view]
fn top_scores() -> impl Query<Score> { ... }

// after
#[spacetimedb::view(accessor = top_scores, public)]
fn top_scores() -> impl Query<Score> { ... }
Defensive patterns

Strategy: validation

Validate before calling

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

Prevention

When it happens

Trigger: `#[spacetimedb::view]` (or with other args such as `name = ...` only) on a fn without `accessor = ...`.

Common situations: Writing a first view following older documentation; migrating views from a version where the accessor was implicit.

Related errors


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