{"record":{"id":"40053b9610527795","repo":"clockworklabs/SpacetimeDB","slug":"unions-not-supported","errorCode":null,"errorMessage":"unions not supported","messagePattern":"unions not supported","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"crates/bindings-macro/src/sats.rs","lineNumber":82,"sourceCode":"                ty: &field.ty,\n                original_attrs: &field.attrs,\n            });\n            SatsTypeData::Product(fields.collect())\n        }\n        syn::Data::Enum(enu) => {\n            let variants = enu.variants.iter().map(|var| {\n                let (member, ty) = variant_data(var)?.unzip();\n                Ok(SatsVariant {\n                    ident: &var.ident,\n                    name: var.ident.to_string(),\n                    ty,\n                    member,\n                    original_attrs: &var.attrs,\n                })\n            });\n            SatsTypeData::Sum(variants.collect::<syn::Result<Vec<_>>>()?)\n        }\n        syn::Data::Union(u) => return Err(syn::Error::new(u.union_token.span, \"unions not supported\")),\n    };\n    extract_sats_type(&input.ident, &input.generics, &input.attrs, data, crate_fallback)\n}\n\nfn is_repr_c(attrs: &[syn::Attribute]) -> bool {\n    let mut is_repr_c = false;\n    for attr in attrs.iter().filter(|a| a.path() == sym::repr) {\n        let _ = attr.parse_nested_meta(|meta| {\n            is_repr_c |= meta.path.is_ident(\"C\");\n            Ok(())\n        });\n    }\n    is_repr_c\n}\n\npub(crate) fn extract_sats_type<'a>(\n    ident: &'a syn::Ident,\n    generics: &'a syn::Generics,","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-macro/src/sats.rs#L64-L100","documentation":"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.","triggerScenarios":"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`.","commonSituations":"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.","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"],"exampleFix":"// before\n#[derive(spacetimedb::SpacetimeType)]\nunion Value {\n    int: i64,\n    text: String,\n}\n\n// after\n#[derive(spacetimedb::SpacetimeType)]\nenum Value {\n    Int(i64),\n    Text(String),\n}","handlingStrategy":"validation","validationCode":"// tests/ui.rs — encode unsupported constructs as expected compile failures in CI\n#[test]\nfn ui() {\n    let t = trybuild::TestCases::new();\n    t.compile_fail(\"tests/ui/union_sats_type.rs\"); // expects \"unions not supported\"\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","proc-macro","spacetimedb","union","compile-time"],"backgroundTag":"unsupported-type-declaration","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}