clockworklabs/SpacetimeDB · error · Error

Invalid UUID: must be between 0 and `MAX_UUID_BIGINT`

Error message

Invalid UUID: must be between 0 and `MAX_UUID_BIGINT`

What it means

A table declared #[spacetimedb::table(scheduled = reducer)] must contain the scheduling columns: #[primary_key] #[auto_inc] scheduled_id: u64 and scheduled_at: spacetimedb::ScheduleAt. When validation finds neither a scheduled_at column (default name or an at = ... override) nor a primary-key column, the macro emits this combined 'add these columns' template instead of two separate errors.

Solutions

  1. Add both required columns verbatim: #[primary_key] #[auto_inc] scheduled_id: u64, and scheduled_at: spacetimedb::ScheduleAt,.
  2. Keep the reducer named by scheduled = ... with a matching scheduled-reducer signature.
  3. Do not rename these columns unless using at = ... for scheduled_at.

Example fix

// before
#[spacetimedb::table(accessor = tick, scheduled = tick_reducer)]
pub struct Tick { pub payload: String }

// after
#[spacetimedb::table(accessor = tick, scheduled = tick_reducer)]
pub struct Tick {
    #[primary_key]
    #[auto_inc]
    scheduled_id: u64,
    scheduled_at: spacetimedb::ScheduleAt,
    pub payload: String,
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Declaring a scheduled table whose struct has only business columns — no scheduled_at field and no primary-key column — e.g. #[spacetimedb::table(scheduled = tick)] struct Tick { payload: String }.

Common situations: Writing the first scheduled reducer; copying a plain table struct and only adding the scheduled argument; following outdated examples that omit the system columns.

Related errors


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

Appendix: source

Thrown at crates/bindings-typescript/src/lib/uuid.ts:77

   * );
   * ```
   */
  static readonly MAX = new Uuid(Uuid.MAX_UUID_BIGINT);

  /**
   * Create a UUID from a raw 128-bit value.
   *
   * @param u - Unsigned 128-bit integer
   * @throws {Error} If the value is outside the valid UUID range
   */
  constructor(u: bigint) {
    // Coerce so callers who arrive via JSON (where bigint precision is
    // lost) hit the range check rather than a cryptic `Cannot mix
    // BigInt and other types` error.
    const v = coerceToBigInt(u, 'Uuid');
    // Must fit in exactly 16 bytes
    if (v < 0n || v > Uuid.MAX_UUID_BIGINT) {
      throw new Error('Invalid UUID: must be between 0 and `MAX_UUID_BIGINT`');
    }
    this.__uuid__ = v;
  }

  /**
   * Create a UUID `v4` from explicit random bytes.
   *
   * This method assumes the bytes are already sufficiently random.
   * It only sets the appropriate bits for the UUID version and variant.
   *
   * @param bytes - Exactly 16 random bytes
   * @returns A UUID `v4`
   * @throws {Error} If `bytes.length !== 16`
   *
   * @example
   * ```ts
   * const randomBytes = new Uint8Array(16);
   * const uuid = Uuid.fromRandomBytesV4(randomBytes);

View on GitHub (pinned to 6dee26c6ef)