clockworklabs/SpacetimeDB · error · InvalidOperationException

Invalid procedure signature.

Error message

Invalid procedure signature.

What it means

Runtime throw from the generated stub for a [Procedure] (value-returning callable). ProcedureDeclaration sets HasWrongSignature=true when the first parameter is not ProcedureContext (Module.cs:1656); GenerateClass then emits a body consisting solely of `throw new System.InvalidOperationException("Invalid procedure signature.")`. The codegen emitted STDB ProcedureContextParam diagnostics at build time; publishing anyway leaves a procedure that always throws when invoked.

Solutions

  1. Give the procedure the exact first parameter: `public static T MyProc(ProcedureContext ctx, ...)`
  2. Verify the return type: a plain serializable type, or ProcedureContext.TxOutcome<T>/TxResult<T,...> for transactional wrapping
  3. Elevate STDB ProcedureContextParam diagnostics to errors in CI so bad signatures cannot ship
  4. Rebuild and republish the module

Example fix

// before
[SpacetimeDB.Procedure]
public static int GetScore(uint playerId) => 42; // missing ProcedureContext

// after
[SpacetimeDB.Procedure]
public static int GetScore(ProcedureContext ctx, uint playerId) => 42;
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Declaring `[Procedure] public static int GetScore(uint id)` without a leading ProcedureContext parameter; adding parameters before the context argument; invoking the procedure from a client once the module is published despite the diagnostic.

Common situations: Writing procedures like plain static functions during prototyping; converting a reducer to a procedure and forgetting to swap ReducerContext for ProcedureContext; ignoring generator diagnostics because the project still compiles (the generated class always compiles).

Related errors


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

Appendix: source

Thrown at crates/bindings-csharp/Codegen/Module.cs:1727

        Scope = new Scope(methodSyntax.Parent as MemberDeclarationSyntax);
    }

    public string GenerateClass()
    {
        var invocationArgs =
            Args.Length == 0 ? "" : ", " + string.Join(", ", Args.Select(a => a.Identifier));
        var invocation = $"{FullName}((SpacetimeDB.ProcedureContext)ctx{invocationArgs})";

        var txPayload = TxPayloadType ?? ReturnType;
        var txPayloadIsUnit = TxPayloadIsUnit;

        string[] bodyLines;

        if (HasWrongSignature)
        {
            bodyLines =
            [
                "throw new System.InvalidOperationException(\"Invalid procedure signature.\");",
            ];
        }
        else if (HasTxWrapper)
        {
            string[] successLines = txPayloadIsUnit
                ? ["return System.Array.Empty<byte>();"]
                :
                [
                    "using var output = new MemoryStream();",
                    "using var writer = new BinaryWriter(output);",
                    "__txReturnRW.Write(writer, outcome.Value!);",
                    "return output.ToArray();",
                ];

            bodyLines =
            [
                $"var outcome = {invocation};",
                "if (!outcome.IsSuccess)",

View on GitHub (pinned to eddf9f5014)