clockworklabs/SpacetimeDB · error · InvalidOperationException

STDB0014

STDB0014

Error message

{Name} is a scheduled table but doesn't have a primary key of type `ulong`.

What it means

STDB0014: the source generator validates tables referenced by a [Scheduled] reducer declaration. The scheduler uses the table's primary key as the schedule handle and requires it to be the C# type `ulong` (the check is an exact match on the type name). A scheduled table without a ulong primary key is reported at build time through the diagnostic and the table is left unusable.

Source

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

        Name = attr.Accessor ?? table.ShortName;
        CanonicalName = attr.Name;
        IsPublic = attr.Public;
        IsEvent = attr.Event;
        if (
            attr.Scheduled is { } reducer
            && table.GetColumnIndex(data, attr.ScheduledAt, diag) is { } scheduledAtIndex
        )
        {
            try
            {
                Scheduled = new(reducer, scheduledAtIndex);
                if (
                    table.GetPrimaryKey(this) is not { } pk
                    || table.Members[pk].Type.Name != "ulong"
                )
                {
                    throw new InvalidOperationException(
                        $"{Name} is a scheduled table but doesn't have a primary key of type `ulong`."
                    );
                }
                if (
                    table.Members[Scheduled.ScheduledAtColumn].Type.Name != "SpacetimeDB.ScheduleAt"
                )
                {
                    throw new InvalidOperationException(
                        $"{Name}.{attr.ScheduledAt} is marked with `ScheduledAt`, but doesn't have the expected type `SpacetimeDB.ScheduleAt`."
                    );
                }
            }
            catch (Exception e)
            {
                diag.Report(ErrorDescriptor.InvalidScheduledDeclaration, (data, e.Message));
            }
        }
    }

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Change the scheduled table's primary key to a plain ulong: [PrimaryKey] [AutoInc] public ulong ScheduleId;
  2. Confirm exactly one member carries [PrimaryKey] and its type is ulong (not nullable, not uint)
  3. Rebuild the module and confirm the STDB0014 diagnostic is gone from compiler output
  4. Model all other identifying data in non-key columns of the scheduled row

Example fix

// before
public struct ScheduledTask
{
    [PrimaryKey] public uint Id; // STDB0014
    public ScheduledAt At;
}

// after
public struct ScheduledTask
{
    [PrimaryKey] [AutoInc] public ulong Id;
    public ScheduledAt At;
}
Defensive patterns

Strategy: validation

Validate before calling

// Build-time contract: scheduled tables must look like this before publishing.
// Assert in a unit test via reflection over the module assembly if you want a CI gate:
// every type referenced by [Scheduled] must expose one [PrimaryKey] member of type ulong.

Prevention

When it happens

Trigger: Declaring the scheduled table's [PrimaryKey] as uint, int, ulong? (nullable), UInt64 spelling edge cases, Identity or Uuid; omitting [PrimaryKey] entirely on a table referenced from [Scheduled(...)].

Common situations: Schema migration where the PK was uint to save space; copying a normal table layout into a scheduled table; renaming the PK property and dropping the attribute by accident.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/c966d180b0adce86. Report an issue: GitHub.