clockworklabs/SpacetimeDB · error

Environment key count exceeds limit

Error message

Environment key count exceeds limit

What it means

Thrown by `render` when the environment read returns more rows than `MAX_ENV_VARS` (spacetimedb_lib::environment::MAX_ENV_VARS). The CLI caps how many environment variables it will process/display, so an over-large result is rejected as inconsistent with server-side limits.

Solutions

  1. Remove unneeded variables with `spacetime env unset KEY` until the count is within the limit.
  2. Upgrade the server so it enforces the same MAX_ENV_VARS cap on writes.
  3. Audit the environment's variables and consolidate related values into fewer keys.

Example fix

// before: 200 keys set, MAX_ENV_VARS = 100
spacetime env list   # Environment key count exceeds limit
// after
spacetime env unset STALE_KEY_1
spacetime env unset STALE_KEY_2   # bring count under the limit
Defensive patterns

Strategy: validation

Validate before calling

// cap env var writes client-side
if var_count > spacetimedb_lib::environment::MAX_ENV_VARS {
    return Err("too many environment variables");
}

Prevention

When it happens

Trigger: `result.rows.len() > MAX_ENV_VARS` — the environment table contains more keys than the enforced maximum, typically because an older server or direct write path allowed exceeding the cap, or a misconfigured environment accumulated too many variables.

Common situations: Inherited environments with many variables set before the limit existed; bulk scripts writing hundreds of env vars via older CLI versions; `spacetime env list` on a long-lived environment.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20). Data as JSON: /api/errors/c7739cc10ba10ded. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/subcommands/env.rs:136

fn render(body: &[u8], query: &Query) -> anyhow::Result<String> {
    // Validate the requested projection before rendering any response values.
    let results: Vec<spacetimedb_client_api_messages::http::SqlStmtResult<Vec<String>>> =
        serde_json::from_slice(body).map_err(|_| anyhow::anyhow!("Invalid environment read response"))?;
    ensure!(results.len() == 1, "Invalid environment read result count");
    let result = &results[0];
    let expected: &[&str] = match query {
        Query::List => &["key", "value"],
        Query::Get(_) => &["value"],
    };
    ensure!(
        result.schema.elements.len() == expected.len()
            && result.schema.elements.iter().zip(expected).all(|(column, name)| {
                column.name.as_deref() == Some(*name) && column.algebraic_type == spacetimedb_lib::AlgebraicType::String
            }),
        "Invalid environment read projection"
    );
    ensure!(result.rows.len() <= MAX_ENV_VARS, "Environment key count exceeds limit");
    for row in &result.rows {
        ensure!(row.len() == expected.len(), "Invalid environment read row");
        if matches!(query, Query::List) {
            validate_key(&row[0]).context("Invalid environment key in response")?;
        }
        ensure!(
            row.last().unwrap().len() <= MAX_ENV_VALUE_BYTES,
            "Environment read value exceeds limit"
        );
    }
    match query {
        Query::List => {
            let mut rows: Vec<_> = result.rows.iter().collect();
            rows.sort_unstable_by(|a, b| a[0].cmp(&b[0]));
            let rows = rows.into_iter().map(|row| {
                Ok::<_, std::convert::Infallible>(spacetimedb_lib::sats::product![row[0].as_str(), row[1].as_str()])
            });
            let table = sql::build_table(

View on GitHub (pinned to eddf9f5014)