clockworklabs/SpacetimeDB · error

Invalid environment read result count

Error message

Invalid environment read result count

What it means

Thrown by `render` when the parsed JSON body is valid `SqlStmtResult` JSON but the top-level array does not contain exactly one statement result. The environment read always issues a single SQL statement, so any other count indicates a protocol mismatch.

Solutions

  1. Align CLI and server versions so the SQL response protocol matches.
  2. Retry the command to rule out a transient server-side glitch.
  3. If you control a proxy, ensure it passes the SQL response through unmodified.
Defensive patterns

Strategy: validation

Type guard

fn is_single_result(r: &[SqlStmtResult<Vec<String>>]) -> bool { r.len() == 1 }

Prevention

When it happens

Trigger: `serde_json` succeeds but `results.len() != 1` — e.g. an empty array from a server that dropped the statement, or multiple results from an incompatible/newer server API.

Common situations: Running a CLI built against a different protocol version than the server; custom proxies splitting statements; server bug returning zero results for the env query.

Related errors


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

Appendix: source

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

    let mut body = Vec::new();
    let limit = MAX_ENV_VARS * (MAX_ENV_KEY_BYTES + MAX_ENV_VALUE_BYTES) * 6 + 64 * 1024;
    let mut stream = response.bytes_stream();
    while let Some(chunk) = stream.next().await {
        let chunk = chunk?;
        ensure!(
            body.len().saturating_add(chunk.len()) <= limit,
            "Environment read response exceeds limit"
        );
        body.extend_from_slice(&chunk);
    }
    render(&body, &query)
}

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")?;
        }

View on GitHub (pinned to eddf9f5014)