clockworklabs/SpacetimeDB · error · InvalidOperationException

Unsupported type

Error message

Unsupported type {type}

What it means

TypeUse.Parse inside the BSATN C# source generator maps a Roslyn type symbol to a BSATN type node. It understands arrays, named types (including Nullable<T>), type parameters, enums and value/reference types; the final `_` arm throws InvalidOperationException for symbol kinds it cannot map — pointer types, function pointers, `dynamic`, and similar non-array/non-named symbols.

Solutions

  1. Replace the offending type with a BSATN-supported one — the message names the exact symbol that failed
  2. Store fixed binary data as byte[] instead of pointers
  3. Restrict schema types to: primitives, string, byte[], arrays/List<T>/IEnumerable<T>, [SpacetimeDB.Type] enums and records, SpacetimeDB.I128/U128/I256/U256
  4. Rebuild after the change — this fails at compile time, so a clean build means the schema is clean

Example fix

// before
[SpacetimeDB.Type]
public partial struct Frame {
    public byte* Data;        // Unsupported type
}

// after
[SpacetimeDB.Type]
public partial struct Frame {
    public byte[] Data;
}
Defensive patterns

Strategy: validation

Validate before calling

// The generator IS the validation: it runs during `dotnet build` and fails fast.
// Keep schema types on this whitelist:
//   bool, sbyte, byte, short, ushort, int, uint, long, ulong, float, double, string,
//   byte[], T[], List<T>, int?, string?,
//   [SpacetimeDB.Type] enums/structs/records,
//   SpacetimeDB.{I128,U128,I256,U256,Identity}
// Anything else (pointers, delegate*, dynamic) is rejected at compile time.

Try / catch

// compile-time error: nothing to catch. Fix the schema type and rebuild.

Prevention

When it happens

Trigger: A table row type, reducer parameter, or [SpacetimeDB.Type]-annotated member in a C# client uses an unmappable type: pointer fields (byte*), function pointers (delegate*<void>), dynamic, or interop-style types carrying unsafe members.

Common situations: Copy-pasting OS-interop or native-struct types into module schema types; unsafe code blocks leaking into row definitions; porting structs from P/Invoke projects.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/89224cae7bb93589. Report an issue: GitHub.

Appendix: source

Thrown at crates/bindings-csharp/BSATN.Codegen/Type.cs:113

                    typeInfo,
                    Parse(member, named.TypeArguments[0], diag),
                    Parse(member, named.TypeArguments[1], diag)
                ),
                "System.Collections.Generic.List<T>" => new ListUse(
                    type,
                    typeInfo,
                    Parse(member, named.TypeArguments[0], diag)
                ),
                "System.Nullable<T>" => new NullableUse(type, typeInfo),
                _ => named.IsValueType
                    ? (
                        named.TypeKind == Microsoft.CodeAnalysis.TypeKind.Enum
                            ? new EnumUse(type, typeInfo)
                            : new ValueUse(type, typeInfo)
                    )
                    : new ReferenceUse(type, typeInfo),
            },
            _ => throw new InvalidOperationException($"Unsupported type {type}"),
        };
    }

    /// <summary>
    /// Get the name of the BSATN struct for this type.
    /// </summary>
    public virtual string ToBSATNString()
    {
        return this.BSATNName;
    }

    public virtual string ToBSATNString2()
    {
        return this.BSATNName;
    }

    /// <summary>
    /// Get a statement that declares outVar and assigns (inVar1 logically-equals inVar2) to it.

View on GitHub (pinned to 6dee26c6ef)