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
- Change the scheduled table's primary key to a plain ulong: [PrimaryKey] [AutoInc] public ulong ScheduleId;
- Confirm exactly one member carries [PrimaryKey] and its type is ulong (not nullable, not uint)
- Rebuild the module and confirm the STDB0014 diagnostic is gone from compiler output
- 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
- Give every scheduled table an auto-increment ulong primary key by convention
- Treat STDB0014 build diagnostics as errors in CI so bad schemas never publish
- Add a code-review checklist item for scheduled tables: [PrimaryKey] ulong + [ScheduledAt] ScheduleAt
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
- never types are not yet supported in C# output
- Invalid procedure signature.
- Invalid HTTP handler signature.
- Missing type name for ${typeBuilder.constructor.name ?? 'Typ
- Unsupported --dotnet-version {version}. Supported values: 8,
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/c966d180b0adce86.
Report an issue: GitHub.