{"record":{"id":"9eb66e2c551a8b5e","repo":"AlexsJones/llmfit","slug":"json-serialization-failed","errorCode":null,"errorMessage":"JSON serialization failed","messagePattern":"JSON serialization failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"llmfit-core/src/quality.rs","lineNumber":594,"sourceCode":"\n    /// Print results as JSON.\n    pub fn display_json(&self) {\n        let json = serde_json::json!({\n            \"quality_benchmark\": {\n                \"model\": self.model,\n                \"provider\": self.provider,\n                \"overall\": {\n                    \"quality\": self.overall_quality,\n                    \"speed\": self.overall_speed,\n                    \"composite\": self.overall_composite,\n                },\n                \"role_scores\": self.roles,\n                \"test_results\": self.test_results,\n            }\n        });\n        println!(\n            \"{}\",\n            serde_json::to_string_pretty(&json).expect(\"JSON serialization failed\")\n        );\n    }\n}\n\nimpl RoutingRecommendation {\n    /// Print a routing matrix row.\n    pub fn display_row(&self) {\n        let note_str = self\n            .note\n            .as_deref()\n            .map(|n| format!(\"  ({})\", n))\n            .unwrap_or_default();\n        println!(\n            \"  {:<17} -> {:<30}  q={:.1}  s={:.1}  c={:.1}{}\",\n            self.role, self.model, self.quality, self.speed, self.composite, note_str\n        );\n    }\n}","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/AlexsJones/llmfit/blob/acc7e40c3a0afbd36510a92f2f8f3d5177cfc0fe/llmfit-core/src/quality.rs#L576-L612","documentation":"An .expect() inside ModelQualityResult::display() (quality.rs) around serde_json::to_string_pretty of a json!-built Value. A Value constructed via the json! macro serializes successfully unless it contains non-finite floats — serde_json rejects NaN/Infinity with 'float must be finite'. Since quality/speed/composite scores are f64 computed from model responses, NaN propagation (e.g. averaging over zero tests, or a rubric score of 0/0) is the realistic trigger for this panic.","triggerScenarios":"A quality run where a scoring computation produces NaN or Infinity (division by zero when no tests succeeded, an errored test contributing NaN that is then averaged) and display() is called to print the JSON summary.","commonSituations":"Benchmarking an endpoint that returns empty/garbage responses so role scores degrade to NaN; refactoring the composite-score formula and introducing an unchecked division.","solutions":["Sanitize scores before display: map non-finite values to 0.0 (or serialize them as null) with a small helper applied to overall_quality/overall_speed/overall_composite and role/test scores","Fix the upstream NaN source — typically a division by a test count that can be zero — so aggregates are computed only over successful tests","Reproduce with `llmfit quality --model ... --json` against the failing endpoint and inspect which score field is NaN before printing"],"exampleFix":"// before (quality.rs)\nprintln!(\"{}\", serde_json::to_string_pretty(&json).expect(\"JSON serialization failed\"));\n\n// after — clamp non-finite floats so Value is always serializable\nfn finite(v: f64) -> f64 { if v.is_finite() { v } else { 0.0 } }\n// ...use finite(self.overall_quality), finite(self.overall_speed), finite(self.overall_composite) when building `json`...","handlingStrategy":"validation","validationCode":"// before printing, assert all scores are finite\nfn all_finite(r: &ModelQualityResult) -> bool {\n    r.overall_quality.is_finite() && r.overall_speed.is_finite() && r.overall_composite.is_finite()\n}\nassert!(all_finite(&result), \"non-finite score — refusing to serialize NaN/Inf\");","typeGuard":"fn finite_score(v: f64) -> Option<f64> {\n    v.is_finite().then_some(v)\n}","tryCatchPattern":null,"preventionTips":["Compute aggregates only over successful tests; guard divisions with a zero-count check","Clamp scores through a finite() helper before building JSON values","Add a unit test serializing a result containing a NaN score to catch regressions"],"tags":["rust","json","serde","nan","panic","display"],"backgroundTag":"json-serialization-failed","analyzedSha":"acc7e40c3a0afbd36510a92f2f8f3d5177cfc0fe","analyzedAt":"2026-08-17T10:35:29.658Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}