clockworklabs/SpacetimeDB · error · TypeError

Math.random is not available in SpacetimeDB modules. Use ctx

Error message

Math.random is not available in SpacetimeDB modules. Use ctx.random instead.

What it means

SpacetimeDB executes JavaScript modules inside a deterministic V8 sandbox and replaces Math.random with a throwing getter (crates/core/src/host/v8/builtins/delete_math_random.js). Randomness must come from the host so execution can be replayed consistently across replicas, so any call to Math.random() raises a TypeError redirecting you to ctx.random.

Source

Thrown at crates/core/src/host/v8/builtins/delete_math_random.js:6

delete Math.random;
Object.defineProperty(Math, 'random', {
  enumerable: false,
  configurable: true,
  get() {
    throw new TypeError(
      'Math.random is not available in SpacetimeDB modules. Use ctx.random instead.'
    );
  },
});

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Replace Math.random() with ctx.random(), using the ReducerContext passed into your reducer or scheduled function
  2. Thread the context (or a () => number closure bound to ctx.random) into helpers and classes that need randomness instead of calling the global
  3. Vendor/patch third-party dependencies to accept an injectable RNG function rather than calling Math.random internally
  4. If you only need uniqueness (ids, tokens), derive values from row ids or Identity instead of RNG

Example fix

// before
function rollDice() { return 1 + Math.floor(Math.random() * 6); }

// after
function rollDice(ctx) { return 1 + Math.floor(ctx.random() * 6); }
Defensive patterns

Strategy: fallback

Validate before calling

// Detect the patched getter WITHOUT invoking it (property access would throw):
const randomIsPatched =
  typeof Object.getOwnPropertyDescriptor(Math, 'random')?.get === 'function';

Type guard

function hasCtxRandom(ctx: unknown): ctx is { random(): number } {
  return !!ctx && typeof (ctx as { random?: unknown }).random === 'function';
}

Try / catch

function safeRandom(ctx?: { random(): number }): number {
  try {
    return Math.random();
  } catch (e) {
    if (e instanceof TypeError && /ctx\.random/.test(e.message)) {
      if (!ctx) throw e;
      return ctx.random();
    }
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling Math.random() anywhere in module code running in the SpacetimeDB V8 host (reducer, scheduled function, module-scope initialization); importing an npm dependency that calls or shims Math.random at load time.

Common situations: Porting existing Node.js or browser game logic; pulling in uuid v4, seedrandom, or noise libraries that self-seed via Math.random; assuming browser/Node globals exist unchanged inside the module sandbox.

Related errors


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