clockworklabs/SpacetimeDB · error · InvalidOperationException
Enum does not have a [SpacetimeDB.Type] attribute
Error message
Enum {type} does not have a [SpacetimeDB.Type] attribute What it means
When a named type is an enum, GetTypeInfoForNamedType requires the [SpacetimeDB.Type] attribute (checked by looking for SpacetimeDB.TypeAttribute) before emitting SpacetimeDB.BSATN.Enum<...>; without it, it throws InvalidOperationException. Enum membership in the module schema is deliberately explicit — the attribute is what makes the generator emit BSATN and client bindings for the enum.
Solutions
- Add [SpacetimeDB.Type] to the enum declaration
- Make sure the attribute resolves — add `using SpacetimeDB;` or fully qualify [SpacetimeDB.Type]
- For third-party enums you cannot edit, store the underlying integer and convert at the edges
- Rebuild after adding the attribute
Example fix
// before
public enum Status { Offline, Online }
[SpacetimeDB.Table(Public = true)]
public partial struct Player {
public Status Status; // throws: no [SpacetimeDB.Type]
}
// after
using SpacetimeDB;
[SpacetimeDB.Type]
public enum Status { Offline, Online }
[SpacetimeDB.Table(Public = true)]
public partial struct Player {
public Status Status;
} Defensive patterns
Strategy: validation
Validate before calling
// Convention check for schema projects (compile-time enforced by the generator): // every enum used in tables/reducers carries [SpacetimeDB.Type] // and `using SpacetimeDB;` is present in that file.
Try / catch
// compile-time error: nothing to catch. Add the attribute and rebuild.
Prevention
- Checklist: tables get [SpacetimeDB.Table]; enums and other row types get [SpacetimeDB.Type]
- For third-party enums, store the underlying int in schema and map in code
- Add a code-review rule that greps new enums for the attribute
When it happens
Trigger: Declaring `enum Status { ... }` without [SpacetimeDB.Type] and then using it as a table column, reducer parameter, or member of another [SpacetimeDB.Type] type. Also triggers when the attribute is spelled differently or comes from another namespace.
Common situations: Assuming enums are picked up automatically the way [SpacetimeDB.Table] tables are; writing [Type] without `using SpacetimeDB;`; using a third-party enum you cannot annotate in a schema type.
Related errors
- Unsupported special type
- Unsupported system type
- Unsupported type
- Unsupported type
- Could not resolve type
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/8bc02cc46ef77257.
Report an issue: GitHub.
Appendix: source
Thrown at crates/bindings-csharp/BSATN.Codegen/Utils.cs:162
? "SpacetimeDB.BSATN.ByteArray"
: $"SpacetimeDB.BSATN.Array<{elementType}, {GetTypeInfo(elementType)}>",
_ => throw new InvalidOperationException($"Unsupported type {type}"),
};
static string GetTypeInfoForNamedType(INamedTypeSymbol type)
{
if (type.TypeKind == Microsoft.CodeAnalysis.TypeKind.Error)
{
throw new UnresolvedTypeException(type);
}
if (type.TypeKind == Microsoft.CodeAnalysis.TypeKind.Enum)
{
if (
!type.GetAttributes()
.Any(a => a.AttributeClass?.ToString() == "SpacetimeDB.TypeAttribute")
)
{
throw new InvalidOperationException(
$"Enum {type} does not have a [SpacetimeDB.Type] attribute"
);
}
return $"SpacetimeDB.BSATN.Enum<{SymbolToName(type)}>";
}
var result = type.OriginalDefinition.ToString() switch
{
// {U/I}{128/256} are not treated by C# as regular primitives, so we need to match them by type name.
"System.Int128" => "SpacetimeDB.BSATN.I128",
"System.UInt128" => "SpacetimeDB.BSATN.U128",
"SpacetimeDB.I128" => "SpacetimeDB.BSATN.I128Stdb",
"SpacetimeDB.U128" => "SpacetimeDB.BSATN.U128Stdb",
"SpacetimeDB.I256" => "SpacetimeDB.BSATN.I256",
"SpacetimeDB.U256" => "SpacetimeDB.BSATN.U256",
"System.Collections.Generic.List<T>" => $"SpacetimeDB.BSATN.List",
"System.Collections.Generic.IEnumerable<T>" => $"SpacetimeDB.BSATN.List",
// If we're here, then this is nullable *value* type like `int?`.
"System.Nullable<T>" => $"SpacetimeDB.BSATN.ValueOption",View on GitHub (pinned to 6dee26c6ef)