{"record":{"id":"05053664e7365c2b","repo":"AlexsJones/llmfit","slug":"json-serialization-failed-050536","errorCode":null,"errorMessage":"JSON serialization failed","messagePattern":"JSON serialization failed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"llmfit-tui/src/display.rs","lineNumber":498,"sourceCode":"        })\n        .collect();\n\n    let table = Table::new(rows).with(Style::rounded()).to_string();\n    println!(\"{}\", table);\n}\n\n// ────────────────────────────────────────────────────────────────────\n// JSON output for machine consumption (OpenClaw skills, scripts, etc.)\n// ────────────────────────────────────────────────────────────────────\n\n/// Serialize system specs to JSON and print to stdout.\npub fn display_json_system(specs: &SystemSpecs) {\n    let output = serde_json::json!({\n        \"system\": system_json(specs),\n    });\n    println!(\n        \"{}\",\n        serde_json::to_string_pretty(&output).expect(\"JSON serialization failed\")\n    );\n}\n\n/// Serialize system specs + model fits to JSON and print to stdout.\npub fn display_json_fits(specs: &SystemSpecs, fits: &[ModelFit]) {\n    let models: Vec<serde_json::Value> = fits.iter().map(fit_to_json).collect();\n    let output = serde_json::json!({\n        \"system\": system_json(specs),\n        \"models\": models,\n    });\n    println!(\n        \"{}\",\n        serde_json::to_string_pretty(&output).expect(\"JSON serialization failed\")\n    );\n}\n\n/// Serialize system specs + model fits to JSON with llama.cpp commands and print to stdout.\npub fn display_json_fits_with_llamacpp(specs: &SystemSpecs, fits: &[ModelFit]) {","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/AlexsJones/llmfit/blob/acc7e40c3a0afbd36510a92f2f8f3d5177cfc0fe/llmfit-tui/src/display.rs#L480-L516","documentation":"This is a panic from .expect(\"JSON serialization failed\") on serde_json::to_string_pretty inside display_json_system, the handler for `llmfit system --json`. The input is a plain serde_json::Value envelope ({\"system\": system_json(specs)}), and to_string_pretty over a Value writes into an in-memory String with no fallible IO, so serde_json can only fail when a value violates the JSON data model (non-finite floats are already coerced to null by Value::from; map-length overflow needs >4 billion entries on 32-bit). The codebase deliberately treats this as an internal invariant per its AGENTS.md convention (expect for internal invariants only), so a panic here indicates a regression in the value produced by system_json/serve_shared::system_json rather than an environmental problem.","triggerScenarios":"Running `llmfit system --json` (or any code path reaching display::display_json_system in llmfit-tui/src/main.rs:2808) after a change that makes the constructed Value unserializable — e.g. a custom Serialize impl in serve_shared::system_json that returns Err, or inserting non-string map keys into the envelope. On 32-bit targets, a map with more than u32::MAX entries would also fail.","commonSituations":"Almost never fires in released builds; typically appears during development after refactoring serve_shared::system_json or adding an exotic field type. CI that pipes JSON output through jq usually catches it first as an abrupt process abort with panic text on stderr.","solutions":["Re-run with RUST_BACKTRACE=1 to confirm the panic originates in display_json_system and not a downstream consumer of stdout.","Run `llmfit system` without --json: if the plain table prints, hardware detection is fine and the fault is purely in the JSON envelope construction — inspect recent changes to serve_shared::system_json (llmfit-tui/src/serve_shared.rs).","Check for newly added field types in the system section whose Serialize impl can error (maps with non-string keys, custom serializers returning Err).","If it reproduces on a clean checkout, file a bug: this expect is documented as an unreachable invariant in this repo.","As a maintainer, convert the expect into a match that prints to stderr and exits 1 if this path ever becomes reachable."],"exampleFix":"// before\nprintln!(\n    \"{}\",\n    serde_json::to_string_pretty(&output).expect(\"JSON serialization failed\")\n);\n\n// after\nmatch serde_json::to_string_pretty(&output) {\n    Ok(json) => println!(\"{json}\"),\n    Err(e) => {\n        eprintln!(\"error: failed to serialize system JSON output: {e}\");\n        std::process::exit(1);\n    }\n}","handlingStrategy":"validation","validationCode":"// Pre-flight: prove the envelope serializes before the printing function panics.\nlet output = serde_json::json!({ \"system\": crate::serve_shared::system_json(specs) });\nif serde_json::to_string_pretty(&output).is_err() {\n    eprintln!(\"system JSON payload is not serializable; refusing to print\");\n    return;\n}\ndisplay::display_json_system(specs);","typeGuard":null,"tryCatchPattern":"// Last-resort guard around a panicking display call (CLI process boundary):\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    display::display_json_system(&specs);\n}));\nif result.is_err() {\n    eprintln!(\"error: JSON output stage failed; this is a bug — please report it\");\n    std::process::exit(1);\n}","preventionTips":["Run `llmfit system --json | jq .` in CI so envelope regressions fail loudly before release.","Keep serve_shared::system_json returning plain string/number/bool/array/object values; never insert map keys that are not strings.","Add a unit test asserting serde_json::to_string_pretty on the built Value succeeds for a mocked SystemSpecs."],"tags":["rust","serde-json","panic","cli","internal-invariant"],"backgroundTag":"json-serialization-failed","analyzedSha":"acc7e40c3a0afbd36510a92f2f8f3d5177cfc0fe","analyzedAt":"2026-08-17T10:35:29.658Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}