clockworklabs/SpacetimeDB · error · anyhow::Error

getrandom usage detected. It seems like either you or a…

Error message

getrandom usage detected.

It seems like either you or a crate in your dependency tree is depending on
the `getrandom` crate for random number generation. getrandom is the default
randomness source for the `rand` crate, and is used when you call
`rand::random()` or `rand::thread_rng()`. If this is you, you should instead
use `ctx.rng()` on a `ReducerContext`. If this is a crate in your
tree, you should try to see if the crate provides a way to pass in a custom
`Rng` type, and pass it the rng returned from `ctx.rng()`.

What it means

SpacetimeDB modules are deterministic and sandboxed: OS entropy is not available, so the `getrandom` backend that the `rand` crate uses by default cannot be satisfied by the host. check_for_issues detects the `__getrandom_custom` import in the compiled wasm and rejects the module, directing you to the host-provided RNG on ReducerContext. Reducers that need randomness must use ctx.rng().

Solutions

  1. Replace rand::random()/thread_rng() with the reducer's ReducerContext RNG: `use rand::Rng; let n = ctx.rng().gen();`
  2. For dependencies, pass randomness in: construct them with an API that accepts a custom Rng and give it `ctx.rng()` (or StdRng::from_rng(ctx.rng()))
  3. Disable random-sourcing features (e.g. uuid's `v4`) and generate the IDs from ctx.rng() yourself
  4. Rebuild and publish

Example fix

// before
let roll: u32 = rand::random();

// after
use rand::Rng;
let roll: u32 = ctx.rng().gen(); // ctx: ReducerContext
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
# module code must not source OS entropy directly
if grep -RnE 'rand::random|thread_rng|OsRng' --include='*.rs' src/; then
  echo 'ERROR: use ctx.rng() instead of OS randomness' >&2
  exit 1
fi

Prevention

When it happens

Trigger: Module code calling rand::random() or rand::thread_rng(); or a dependency that internally sources entropy itself (uuid::Uuid::new_v4 with default `v4` features, nanoid-style crates, anything constructing OsRng) rather than accepting an injected Rng.

Common situations: Porting game code that rolls dice with rand::random(); generating UUIDs server-side in a reducer; a helper crate that defaults to ThreadRng/OsRng internally.

Related errors


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

Appendix: source

Thrown at crates/cli/src/tasks/rust.rs:133

    };
    let Ok(module) = wasmbin::Module::decode_from(&mut io::BufReader::new(file)) else {
        return Ok(());
    };
    if has_wasm_bindgen(&module) {
        anyhow::bail!(
            "wasm-bindgen detected.\n\
             \n\
             It seems like either you or a crate in your dependency tree is depending on\n\
             wasm-bindgen. wasm-bindgen is only for webassembly modules that target the web\n\
             platform, and will not work in the context of SpacetimeDB.\n\
             \n\
             To find the offending dependency, run `cargo tree -i wasm-bindgen`. Try checking\n\
             its cargo features for 'js' or 'web' or 'wasm-bindgen' to see if there's a way\n\
             to disable it."
        )
    }
    if has_getrandom(&module) {
        anyhow::bail!(
            "getrandom usage detected.\n\
             \n\
             It seems like either you or a crate in your dependency tree is depending on\n\
             the `getrandom` crate for random number generation. getrandom is the default\n\
             randomness source for the `rand` crate, and is used when you call\n\
             `rand::random()` or `rand::thread_rng()`. If this is you, you should instead\n\
             use `ctx.rng()` on a `ReducerContext`. If this is a crate in your\n\
             tree, you should try to see if the crate provides a way to pass in a custom\n\
             `Rng` type, and pass it the rng returned from `ctx.rng()`."
        )
    }
    Ok(())
}

const WBINDGEN_PREFIX: &str = "__wbindgen";
fn has_wasm_bindgen(module: &wasmbin::Module) -> bool {
    let check_import = |import: &wasmbin::sections::Import| {
        import.path.module.starts_with(WBINDGEN_PREFIX) || import.path.name.starts_with(WBINDGEN_PREFIX)

View on GitHub (pinned to 6dee26c6ef)