{"record":{"id":"77b1870ab79f98f2","repo":"Hmbown/CodeWhale","slug":"serialize","errorCode":null,"errorMessage":"serialize","messagePattern":"serialize","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/models/src/model_catalog.rs","lineNumber":366,"sourceCode":"            MergedCatalog::from_sources(BTreeMap::new(), Some(provider_cache), bundled, now);\n        let resolved = merged.resolve(\"sample/model\").expect(\"resolved\");\n        assert_eq!(resolved.context_window, Some(1_000));\n        assert_eq!(resolved.provenance, MetadataProvenance::Bundled);\n    }\n\n    #[test]\n    fn cache_roundtrip_serializes_no_secret_fields() {\n        let mut entries = BTreeMap::new();\n        entries.insert(\n            \"sample/model\".to_string(),\n            CatalogEntry {\n                input_usd_per_million: Some(0.25),\n                output_usd_per_million: Some(1.25),\n                ..entry(\"sample/model\", 32_000, MetadataProvenance::ProviderApi)\n            },\n        );\n        let cache = cache(Utc::now(), 60, entries);\n        let json = serde_json::to_string_pretty(&cache).expect(\"serialize\");\n        let lowered = json.to_lowercase();\n        for forbidden in [\"api_key\", \"authorization\", \"token\", \"secret\"] {\n            assert!(\n                !lowered.contains(forbidden),\n                \"cache JSON must not contain auth field {forbidden}: {json}\"\n            );\n        }\n        let parsed: CatalogCache = serde_json::from_str(&json).expect(\"roundtrip\");\n        assert_eq!(parsed.entries.len(), 1);\n    }\n}\n","sourceCodeStart":348,"sourceCodeEnd":378,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/models/src/model_catalog.rs#L348-L378","documentation":"`cache_roundtrip_serializes_no_secret_fields` calls `serde_json::to_string_pretty(&cache).expect(\"serialize\")`, panicking if `CatalogCache` fails to serialize to JSON. With serde this essentially only fails if a field's serializer errors (e.g. a non-string key map or a custom Serialize returning Err) — normally it cannot fail, so the expect is a belt-and-braces guard in the test.","triggerScenarios":"Adding a field to `CatalogCache` or `ModelEntry` whose `Serialize` impl returns Err (e.g. a map with non-string keys, or a manual impl writing via a failing formatter); swapping serde_json for a serializer that rejects the type shape.","commonSituations":"Introducing custom serialization for credentials or cost fields; using `serde_json::to_writer` with types that changed from struct to map-of-enums.","solutions":["Check any custom `Serialize` impls added to `CatalogCache`/`ModelEntry` for `Err` returns","Ensure all serialized fields are JSON-compatible (string map keys, plain values)","Reproduce with a minimal `serde_json::to_string(&cache)` call and inspect the serde error message"],"exampleFix":"// before\nlet json = serde_json::to_string_pretty(&cache).expect(\"serialize\");\n// after\nlet json = serde_json::to_string_pretty(&cache)\n    .unwrap_or_else(|e| panic!(\"cache serialize failed: {e}\"));","handlingStrategy":"try-catch","validationCode":"// Serialize-ability can be checked cheaply in debug builds\ndebug_assert!(serde_json::to_string(&cache).is_ok(), \"CatalogCache must remain JSON-serializable\");","typeGuard":null,"tryCatchPattern":"let json = serde_json::to_string_pretty(&cache)\n    .unwrap_or_else(|e| panic!(\"CatalogCache serialization failed: {e}\"));","preventionTips":["Prefer derived Serialize/Deserialize; avoid custom impls that can return Err","Keep all cache fields JSON-compatible (string keys, no non-string map keys)","Add a roundtrip test whenever CatalogCache gains a field"],"tags":["rust","serde","json","serialization"],"backgroundTag":"json-serialization-failed","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}