Hmbown/CodeWhale · info
Concentrate catalog delta
Error message
Concentrate catalog delta
What it means
This .expect("Concentrate catalog delta") is in crates/tui/src/client.rs:7717, unwrapping the Result of ConcentrateClient::fetch_catalog_delta() in a test that mounts a mock catalog endpoint. It panics when the client cannot fetch or parse the provider's model catalog delta.
Solutions
- Read the panic's error payload: a 404 means the mock route path/method no longer matches; a serde error names the mismatched JSON field.
- Compare the mounted mock JSON against the CatalogDelta deserialization types and fix whichever drifted.
- Verify the client is constructed with the same base URL the mock server exposes.
- Re-run `cargo test -p codewhale-tui fetch_catalog` style filters after the fix; the test then asserts provider==concentrate and 3 offerings.
Example fix
// before
let delta = concentrate_client(&server, DEFAULT_CONCENTRATE_MODEL)
.fetch_catalog_delta()
.await
.expect("Concentrate catalog delta");
// after
let delta = concentrate_client(&server, DEFAULT_CONCENTRATE_MODEL)
.fetch_catalog_delta()
.await
.unwrap_or_else(|e| panic!("Concentrate catalog delta failed: {e:?}")); Defensive patterns
Strategy: try-catch
Try / catch
// surface the underlying error instead of a bare expect
match client.fetch_catalog_delta().await {
Ok(delta) => { /* assertions on delta */ }
Err(e) => panic!("catalog delta fetch failed: {e:?}"),
} Prevention
- Keep the catalog mock fixture and the CatalogDelta serde types in lockstep; bump both when fields change.
- Mount all mocks before constructing/using the client.
- Assert the client's base URL matches the wiremock server URI.
When it happens
Trigger: fetch_catalog_delta() returning Err: the mock route for the catalog endpoint is missing or returns a non-2xx body, the response JSON doesn't match the expected catalog schema, or the request fails transport-wise (client misconfigured to wrong base URL).
Common situations: Changing the gateway catalog response shape (renamed fields like offerings/wire_model_id) without updating the deserializer; forgetting to mount the mock before calling; provider base-URL config drift so the client hits an unmocked path.
Related errors
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/94027b51d32f1ed0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client.rs:7717
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/v1/models"))
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
"object": "list",
"data": [
{"id": "claude-fable-5", "object": "model", "owned_by": "anthropic"},
{"id": DEFAULT_CONCENTRATE_MODEL, "object": "model", "owned_by": "deepseek"},
{"id": "gpt-5.6-sol", "object": "model", "owned_by": "openai"}
]
})))
.expect(1)
.mount(&server)
.await;
let delta = concentrate_client(&server, DEFAULT_CONCENTRATE_MODEL)
.fetch_catalog_delta()
.await
.expect("Concentrate catalog delta");
assert_eq!(delta.provider, "concentrate");
assert_eq!(delta.offerings.len(), 3);
let default = delta
.offerings
.iter()
.find(|offering| offering.wire_model_id == DEFAULT_CONCENTRATE_MODEL)
.expect("default row");
assert!(default.default_for_provider);
let unknown = delta
.offerings
.iter()
.find(|offering| offering.wire_model_id == "claude-fable-5")
.expect("unclaimed row");
assert!(!unknown.default_for_provider);
assert_eq!(unknown.canonical_model, None);
assert_eq!(
unknown.cost, None,
"no pricing claim from a gateway catalog"View on GitHub (pinned to 73e0f67d83)