clockworklabs/SpacetimeDB · error

Environment read response exceeds limit

Error message

Environment read response exceeds limit

What it means

Thrown by `fetch` while streaming the HTTP response body for an environment read. The body is accumulated chunk-by-chunk and rejected as soon as its size would exceed `MAX_ENV_VARS * (MAX_ENV_KEY_BYTES + MAX_ENV_VALUE_BYTES) * 6 + 64 * 1024` bytes — the maximum plausible size of a fully populated env-var table. This protects the CLI from unbounded/hijacked responses.

Solutions

  1. Verify the server URL points at a real SpacetimeDB node, not another HTTP service.
  2. Retry; a one-off large error page from a proxy could be the cause.
  3. Check for reverse proxies/load balancers rewriting or enlarging responses.
  4. If legitimately huge, reduce the number of environment variables or value sizes stored in the environment.
Defensive patterns

Strategy: retry

Try / catch

if err.contains("Environment read response exceeds limit") {
    // verify server URL / proxy, then retry; fail permanently if it recurs
}

Prevention

When it happens

Trigger: The server (or an intermediary) returns more than the computed limit of bytes on the `bytes_stream()` of the environment-read query — e.g. a misbehaving proxy, a wrong endpoint returning a large payload, or a server bug dumping the whole database.

Common situations: Pointing the CLI at a non-SpacetimeDB endpoint that answers the SQL request with a large HTML/JSON body; a compromised or misconfigured reverse proxy; a server version whose response format changed drastically.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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

Appendix: source

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

async fn fetch(request: reqwest::RequestBuilder, query: Query) -> anyhow::Result<String> {
    use futures::StreamExt;
    let response = request
        .timeout(std::time::Duration::from_secs(30))
        .body(query.sql()?)
        .send()
        .await?;
    ensure!(
        response.status().is_success(),
        "Environment read failed with HTTP {}",
        response.status()
    );
    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"],
    };

View on GitHub (pinned to eddf9f5014)