clockworklabs/SpacetimeDB · error
Invalid environment read response
Error message
Invalid environment read response
What it means
Thrown by `render` when the accumulated response body of an environment read cannot be parsed as JSON into `Vec<spacetimedb_client_api_messages::http::SqlStmtResult<Vec<String>>>`. The CLI expects the HTTP SQL endpoint's standard statement-result shape; anything else is rejected before rendering.
Solutions
- Check that CLI and server versions match (`spacetime version`); upgrade or downgrade to align them.
- Inspect the raw response (e.g. with `curl`) to see what the server actually returned.
- Confirm you are calling the /v1/database/sql endpoint of a SpacetimeDB server.
- Retry in case the response was truncated by a network fault.
Example fix
// server returned HTML due to wrong URL // before --server https://example.com # serves HTML // after --server https://spacetimedb.example.com # actual SpacetimeDB node
Defensive patterns
Strategy: validation
Validate before calling
// before parsing, sanity-check the body looks like JSON array output
if !body.trim_start().starts_with('[') {
return Err("server did not return SQL statement results");
} Type guard
fn looks_like_stmt_results(body: &[u8]) -> bool {
serde_json::from_slice::<serde_json::Value>(body)
.map(|v| v.is_array())
.unwrap_or(false)
} Prevention
- Keep CLI and server versions aligned.
- Do not place HTML-generating proxies in front of the SQL endpoint.
- Log raw response bodies on parse failure for diagnosis.
When it happens
Trigger: `serde_json::from_slice(body)` fails — the server returned non-JSON (HTML error page, empty body, truncated stream) or JSON in an unexpected shape (object instead of array, different field types).
Common situations: CLI version mismatched with server version so the SQL response schema differs; a proxy returning an HTML error page; hitting the wrong URL path.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Invalid environment read result count
- Invalid environment read row
- Invalid publish response
- Cannot extract accessor name from query
- Cannot extract table name from query
AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20).
Data as JSON: /api/errors/fb0de3d8fced11a6.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/subcommands/env.rs:122
);
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)