{"record":{"id":"871ee7ba506f358e","repo":"clockworklabs/SpacetimeDB","slug":"unsupported-system-type-name","errorCode":null,"errorMessage":"Unsupported system type {name}","messagePattern":"Unsupported system type (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"crates/bindings-csharp/BSATN.Codegen/Utils.cs","lineNumber":181,"sourceCode":"                        $\"Enum {type} does not have a [SpacetimeDB.Type] attribute\"\n                    );\n                }\n                return $\"SpacetimeDB.BSATN.Enum<{SymbolToName(type)}>\";\n            }\n            var result = type.OriginalDefinition.ToString() switch\n            {\n                // {U/I}{128/256} are not treated by C# as regular primitives, so we need to match them by type name.\n                \"System.Int128\" => \"SpacetimeDB.BSATN.I128\",\n                \"System.UInt128\" => \"SpacetimeDB.BSATN.U128\",\n                \"SpacetimeDB.I128\" => \"SpacetimeDB.BSATN.I128Stdb\",\n                \"SpacetimeDB.U128\" => \"SpacetimeDB.BSATN.U128Stdb\",\n                \"SpacetimeDB.I256\" => \"SpacetimeDB.BSATN.I256\",\n                \"SpacetimeDB.U256\" => \"SpacetimeDB.BSATN.U256\",\n                \"System.Collections.Generic.List<T>\" => $\"SpacetimeDB.BSATN.List\",\n                \"System.Collections.Generic.IEnumerable<T>\" => $\"SpacetimeDB.BSATN.List\",\n                // If we're here, then this is nullable *value* type like `int?`.\n                \"System.Nullable<T>\" => $\"SpacetimeDB.BSATN.ValueOption\",\n                var name when name.StartsWith(\"System.\") => throw new InvalidOperationException(\n                    $\"Unsupported system type {name}\"\n                ),\n                _ => $\"{SymbolToName(type)}.BSATN\",\n            };\n            if (type.IsGenericType)\n            {\n                result =\n                    $\"{result}<{string.Join(\", \", type.TypeArguments.Select(SymbolToName).Concat(type.TypeArguments.Select(GetTypeInfo)))}>\";\n            }\n\n            return result;\n        }\n    }\n\n    // Polyfill for .NET methods from .NET Standard 2.1+:\n    private static StringBuilder AppendJoin<T>(\n        this StringBuilder sb,\n        string separator,","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/bindings-csharp/BSATN.Codegen/Utils.cs#L163-L199","documentation":"For named System.* types, GetTypeInfoForNamedType only knows System.Int128/UInt128, SpacetimeDB.I128/U128/I256/U256, List<T>, IEnumerable<T> and Nullable<T>. Any other type whose original-definition name starts with 'System.' — Dictionary<K,V>, HashSet<T>, Guid, DateTime, TimeSpan, KeyValuePair, System.Numerics.* — throws InvalidOperationException, refusing to guess a BSATN layout for BCL types it has no mapping for.","triggerScenarios":"Using Dictionary<K,V>, HashSet<T>, KeyValuePair<,>, Guid, DateTime, DateTimeOffset, TimeSpan, System.Numerics.BigInteger or any unmapped System.* type in a table column, reducer argument, or [SpacetimeDB.Type] member.","commonSituations":"Bringing in domain models with dictionary lookups; using Guid as a player identifier where SpacetimeDB.Identity is intended; DateTime timestamps; HashSet sets copied from server logic.","solutions":["Replace Dictionary<K,V> with List<T> of a [SpacetimeDB.Type] key/value entry struct","Use SpacetimeDB.Identity instead of Guid for player/entity ids","Map DateTime/DateTimeOffset/TimeSpan to long (ticks or unix microseconds)","Replace HashSet<T> with List<T> and dedupe inside reducer logic"],"exampleFix":"// before\n[SpacetimeDB.Type]\npublic partial struct Settings {\n    public Dictionary<string, int> Flags;\n    public Guid PlayerGuid;\n    public DateTime UpdatedAt;\n}\n\n// after\n[SpacetimeDB.Type]\npublic partial struct FlagEntry { public string Key; public int Value; }\n\n[SpacetimeDB.Type]\npublic partial struct Settings {\n    public List<FlagEntry> Flags;\n    public SpacetimeDB.Identity PlayerId;\n    public long UpdatedAtMicros;\n}","handlingStrategy":"validation","validationCode":"// Compile-time: the generator rejects unmapped System.* types.\n// Replacement map to apply to schema members:\n//   Dictionary<K,V> -> List<EntryStruct> ([SpacetimeDB.Type] { K Key; V Value; })\n//   HashSet<T>      -> List<T>\n//   Guid            -> SpacetimeDB.Identity (or byte[16])\n//   DateTime        -> long micros\n//   TimeSpan        -> long micros","typeGuard":null,"tryCatchPattern":"// compile-time error: nothing to catch. Replace the System.* type and rebuild.","preventionTips":["Never put BCL collections or Guid/DateTime directly in schema types","Maintain a small library of pre-approved schema DTOs and map domain models onto them","Rebuild immediately after adding fields — the error names the offending type"],"tags":["csharp","source-generator","bsatn","schema","unsupported-type"],"backgroundTag":"codegen-unsupported-type","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}