{"record":{"id":"7018c63354ab2b78","repo":"clockworklabs/SpacetimeDB","slug":"invalid-environment-read-projection","errorCode":null,"errorMessage":"Invalid environment read projection","messagePattern":"Invalid environment read projection","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/subcommands/env.rs","lineNumber":129,"sourceCode":"            body.len().saturating_add(chunk.len()) <= limit,\n            \"Environment read response exceeds limit\"\n        );\n        body.extend_from_slice(&chunk);\n    }\n    render(&body, &query)\n}\n\nfn render(body: &[u8], query: &Query) -> anyhow::Result<String> {\n    // Validate the requested projection before rendering any response values.\n    let results: Vec<spacetimedb_client_api_messages::http::SqlStmtResult<Vec<String>>> =\n        serde_json::from_slice(body).map_err(|_| anyhow::anyhow!(\"Invalid environment read response\"))?;\n    ensure!(results.len() == 1, \"Invalid environment read result count\");\n    let result = &results[0];\n    let expected: &[&str] = match query {\n        Query::List => &[\"key\", \"value\"],\n        Query::Get(_) => &[\"value\"],\n    };\n    ensure!(\n        result.schema.elements.len() == expected.len()\n            && result.schema.elements.iter().zip(expected).all(|(column, name)| {\n                column.name.as_deref() == Some(*name) && column.algebraic_type == spacetimedb_lib::AlgebraicType::String\n            }),\n        \"Invalid environment read projection\"\n    );\n    ensure!(result.rows.len() <= MAX_ENV_VARS, \"Environment key count exceeds limit\");\n    for row in &result.rows {\n        ensure!(row.len() == expected.len(), \"Invalid environment read row\");\n        if matches!(query, Query::List) {\n            validate_key(&row[0]).context(\"Invalid environment key in response\")?;\n        }\n        ensure!(\n            row.last().unwrap().len() <= MAX_ENV_VALUE_BYTES,\n            \"Environment read value exceeds limit\"\n        );\n    }\n    match query {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/eddf9f5014579a50d4b67630e28b6e15cad9c4af/crates/cli/src/subcommands/env.rs#L111-L147","documentation":"Thrown by `render` when the single SQL statement result's schema does not match the expected projection: for `Query::List` the columns must be exactly `key` and `value`, for `Query::Get` exactly `value`, all of `AlgebraicType::String`. This validates the server returned the exact requested columns before rendering values.","triggerScenarios":"`result.schema.elements` has a different length, column names, or column types than the expected projection — e.g. the server ignored the projection, renamed columns, or returned a different type.","commonSituations":"Server/CLI version mismatch changing SQL result metadata; a custom server or proxy altering the schema; querying a non-standard endpoint that echoes a full-table schema.","solutions":["Upgrade or downgrade the CLI to match the server version.","Verify the environment-read SQL used matches the current server's supported syntax.","If behind a proxy, ensure it does not rewrite the SQL response schema.","Report/inspect the raw JSON response to see the actual column names and types."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// confirm expected columns before use\nassert_eq!(result.schema.elements.len(), expected.len());","typeGuard":"fn has_expected_schema(r: &SqlStmtResult<Vec<String>>, expected: &[&str]) -> bool {\n    r.schema.elements.len() == expected.len()\n        && r.schema.elements.iter().zip(expected)\n            .all(|(c, n)| c.name.as_deref() == Some(*n))\n}","tryCatchPattern":null,"preventionTips":["Upgrade CLI and server together.","Do not transform SQL responses in intermediaries.","Assert schema in CI against your server version."],"tags":["cli","spacetimedb","schema","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"eddf9f5014579a50d4b67630e28b6e15cad9c4af","analyzedAt":"2026-09-20T12:15:59.611Z","contentChangedAt":"2026-09-20T12:15:59.611Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}