Hmbown/CodeWhale · error
serialize
Error message
serialize
What it means
`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.
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
Example fix
// before
let json = serde_json::to_string_pretty(&cache).expect("serialize");
// after
let json = serde_json::to_string_pretty(&cache)
.unwrap_or_else(|e| panic!("cache serialize failed: {e}")); Defensive patterns
Strategy: try-catch
Validate before calling
// Serialize-ability can be checked cheaply in debug builds debug_assert!(serde_json::to_string(&cache).is_ok(), "CatalogCache must remain JSON-serializable");
Try / catch
let json = serde_json::to_string_pretty(&cache)
.unwrap_or_else(|e| panic!("CatalogCache serialization failed: {e}")); Prevention
- 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
When it happens
Trigger: 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.
Common situations: Introducing custom serialization for credentials or cost fields; using `serde_json::to_writer` with types that changed from struct to map-of-enums.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- serialize
- deserialize
- <dynamic: wrapped serde_json serialization error>
- <dynamic: wrapped serde_json serialization error>
- roundtrip
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/77b1870ab79f98f2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/models/src/model_catalog.rs:366
MergedCatalog::from_sources(BTreeMap::new(), Some(provider_cache), bundled, now);
let resolved = merged.resolve("sample/model").expect("resolved");
assert_eq!(resolved.context_window, Some(1_000));
assert_eq!(resolved.provenance, MetadataProvenance::Bundled);
}
#[test]
fn cache_roundtrip_serializes_no_secret_fields() {
let mut entries = BTreeMap::new();
entries.insert(
"sample/model".to_string(),
CatalogEntry {
input_usd_per_million: Some(0.25),
output_usd_per_million: Some(1.25),
..entry("sample/model", 32_000, MetadataProvenance::ProviderApi)
},
);
let cache = cache(Utc::now(), 60, entries);
let json = serde_json::to_string_pretty(&cache).expect("serialize");
let lowered = json.to_lowercase();
for forbidden in ["api_key", "authorization", "token", "secret"] {
assert!(
!lowered.contains(forbidden),
"cache JSON must not contain auth field {forbidden}: {json}"
);
}
let parsed: CatalogCache = serde_json::from_str(&json).expect("roundtrip");
assert_eq!(parsed.entries.len(), 1);
}
}
View on GitHub (pinned to 433685b202)