{"record":{"id":"98a93c1483e4f3e5","repo":"xai-org/x-algorithm","slug":"e","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"error_code","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"thunder/strato_client.rs","lineNumber":159,"sourceCode":"\n        match serde_json::from_str::<StratoResponse<Vec<String>>>(&text) {\n            Ok(result) => {\n                metrics::STRATO_REQUESTS\n                    .with_label_values(&[\"fetch_following_list\", \"success\"])\n                    .inc();\n                Ok(result.v)\n            }\n            Err(e) => {\n                metrics::STRATO_REQUESTS\n                    .with_label_values(&[\"fetch_following_list\", \"parse_error\"])\n                    .inc();\n                warn!(\n                    \"Failed to parse following list response for {}: {}. Response preview: {}\",\n                    user_id,\n                    e,\n                    &text[..text.len().min(300)]\n                );\n                Err(anyhow!(e))\n            }\n        }\n    }\n\n    pub async fn fetch_user_metadata(&self, user_id: i64) -> Result<Option<UserMetadata>> {\n        let start = std::time::Instant::now();\n\n        let url = format!(\"{}/op/fetch/gizmoduck/composite.User\", self.base_url);\n\n        let payload = serde_json::json!([user_id, (serde_json::json!({}), [\"profile\", \"counts\"])]);\n\n        let response = self\n            .client\n            .post(&url)\n            .header(\"Content-Type\", \"application/json\")\n            .body(serde_json::to_string(&payload)?)\n            .send()\n            .await","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/thunder/strato_client.rs#L141-L177","documentation":"Returned by fetch_following_list_internal when serde_json fails to parse the Strato response body as StratoResponse<Vec<String>>. The warn log already prints the error and a 300-char response preview, which usually reveals whether the body is HTML (error page), truncated, or a different schema.","triggerScenarios":"Calling fetch_following_list when Strato returns a 200 with an unexpected body: an HTML error/proxy page, a different response schema after an API change, or truncated/garbled payloads from network issues.","commonSituations":"A proxy or LB intercepting the request and returning HTML; Strato API version change altering the JSON shape; encoding/compression (gzip not decompressed) issues; partial responses on connection resets.","solutions":["Inspect the warn log's response preview to identify what was actually returned","If HTML from a proxy, check the Strato endpoint URL/LB config and any required headers (auth, accept-encoding)","If the schema changed, update StratoResponse<Vec<String>> to match the current Strato API shape","Verify HTTP client decompression settings so gzip/br bodies are decoded before parsing"],"exampleFix":"// before\nmatch serde_json::from_str::<StratoResponse<Vec<String>>>(&text) {\n    Ok(result) => { ... }\n    Err(e) => Err(anyhow!(e)),\n}\n\n// after\nmatch serde_json::from_str::<StratoResponse<Vec<String>>>(&text) {\n    Ok(result) => { ... }\n    Err(e) => Err(anyhow::anyhow!(\n        \"strato parse failed for user {user_id}: {e}; body starts: {}\",\n        &text[..text.len().min(120)]\n    )),\n}","handlingStrategy":"try-catch","validationCode":"// sanity check body shape before parse: starts with '{' and contains \"data\" key","typeGuard":null,"tryCatchPattern":"match serde_json::from_str::<StratoResponse<Vec<String>>>(&text) { Ok(r) => ..., Err(e) if text.trim_start().starts_with('<') => anyhow::bail!(\"proxy HTML page returned\"), Err(e) => Err(anyhow!(e)) }","preventionTips":["Assert Content-Type is JSON on responses","Pin schema with contract tests against Strato","Log body previews on parse failure (already done) and alert on spikes"],"tags":["json","parse-error","strato","schema-change","rust"],"backgroundTag":"json-parse-error","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}