clockworklabs/SpacetimeDB · error · syn::Error
unions not supported
Error message
unions not supported
What it means
The SpacetimeDB derive macros can only generate SATS schema for Rust structs (product types) and enums (sum types); a `union` has no representation in the SATS type system. When a derive such as `SpacetimeType` or `#[spacetimedb::table(...)]` is applied to a `union` item, `sats_type_from_derive` rejects it at the union token span. Unions are also unsafe to read in general, so no serialization code can be generated for them.
Source
Thrown at crates/bindings-macro/src/sats.rs:82
ty: &field.ty,
original_attrs: &field.attrs,
});
SatsTypeData::Product(fields.collect())
}
syn::Data::Enum(enu) => {
let variants = enu.variants.iter().map(|var| {
let (member, ty) = variant_data(var)?.unzip();
Ok(SatsVariant {
ident: &var.ident,
name: var.ident.to_string(),
ty,
member,
original_attrs: &var.attrs,
})
});
SatsTypeData::Sum(variants.collect::<syn::Result<Vec<_>>>()?)
}
syn::Data::Union(u) => return Err(syn::Error::new(u.union_token.span, "unions not supported")),
};
extract_sats_type(&input.ident, &input.generics, &input.attrs, data, crate_fallback)
}
fn is_repr_c(attrs: &[syn::Attribute]) -> bool {
let mut is_repr_c = false;
for attr in attrs.iter().filter(|a| a.path() == sym::repr) {
let _ = attr.parse_nested_meta(|meta| {
is_repr_c |= meta.path.is_ident("C");
Ok(())
});
}
is_repr_c
}
pub(crate) fn extract_sats_type<'a>(
ident: &'a syn::Ident,
generics: &'a syn::Generics,View on GitHub (pinned to 524b4487d9)
Solutions
- Replace the union with an enum — enums map to SATS sum types and are fully supported
- If the union encoded tagged data, convert it to a struct holding an enum field
- Keep unions out of schema types entirely: convert or wrap them before storing in tables
Example fix
// before
#[derive(spacetimedb::SpacetimeType)]
union Value {
int: i64,
text: String,
}
// after
#[derive(spacetimedb::SpacetimeType)]
enum Value {
Int(i64),
Text(String),
} Defensive patterns
Strategy: validation
Validate before calling
// tests/ui.rs — encode unsupported constructs as expected compile failures in CI
#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/union_sats_type.rs"); // expects "unions not supported"
} Prevention
- Only structs and enums may carry SpacetimeDB derives; keep unions out of schema types
- Add trybuild UI tests for constructs your module must never use
- Run cargo check in CI before spacetime build so macro errors surface early
When it happens
Trigger: Applying `#[derive(SpacetimeType)]` or `#[spacetimedb::table(...)]` to a Rust `union` item; any derive path that feeds a `syn::Data::Union` into `sats_type_from_derive`.
Common situations: Porting C-style FFI code that used `#[repr(C)] union` for zero-cost variants into a SpacetimeDB module; reusing an existing domain type as a table or column type without reshaping it first.
Related errors
- must specify table accessor, e.g. `#[spacetimedb::table(acce
- a direct index must be paired with a `#[unique] constraint
- not a column of the table
- spacetimedb table must be a struct
- 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/40053b9610527795.
Report an issue: GitHub.