{"record":{"id":"f3fbd7bee4a3722d","repo":"juspay/hyperswitch","slug":"a-captured-response-must-reconstruct","errorCode":null,"errorMessage":"a captured response must reconstruct","messagePattern":"a captured response must reconstruct","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/external_services/src/http_client/boundary.rs","lineNumber":274,"sourceCode":"            (\"x-request-id\", \"req-1\"),\n            (\"set-cookie\", \"a=1\"),\n            (\"set-cookie\", \"b=2\"),\n            (\"set-cookie\", \"c=3\"),\n        ] {\n            builder = builder.header(name, value);\n        }\n        let source = reqwest::Response::from(\n            builder\n                .body(bytes::Bytes::from_static(b\"{}\"))\n                .expect(\"failed to build the test response\"),\n        );\n\n        let result: CustomResult<reqwest::Response, HttpClientError> = Ok(source);\n        let (captured, _) = response_result(&result);\n        let captured = captured.expose();\n\n        let reconstructed =\n            replay_response(&captured).expect(\"a captured response must reconstruct\");\n        let cookies: Vec<&str> = reconstructed\n            .headers()\n            .get_all(\"set-cookie\")\n            .iter()\n            .filter_map(|value| value.to_str().ok())\n            .collect();\n        assert_eq!(\n            cookies,\n            [\"a=1\", \"b=2\", \"c=3\"],\n            \"every set-cookie value must survive the round trip\"\n        );\n    }\n\n    /// A recording written before the capture kept repeats stored one string per\n    /// name, having already lost every repeated value. Reconstructing it would\n    /// replay a tape that still carries the defect this fixes, so it refuses —\n    /// and deja turns that refusal into a fail-stop with a named reason rather\n    /// than a live call.","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/juspay/hyperswitch/blob/afd92843521ced2c6856b98ae4ea332e75102d88/crates/external_services/src/http_client/boundary.rs#L256-L292","documentation":"After capturing a response via response_result, the test calls `replay_response(&captured).expect(\"a captured response must reconstruct\")`; if the captured boundary representation cannot be rebuilt into a reqwest::Response, the expect panics. It asserts the capture/reconstruct round-trip invariant of the HTTP boundary layer.","triggerScenarios":"A regression in the capture or replay logic (e.g. repeated `set-cookie` headers dropped or malformed during serialization) makes replay_response return Err.","commonSituations":"Changes to the CustomResponse/CapturedResponse serialization that break multi-valued headers or body reconstruction in the http_client boundary module.","solutions":["Inspect why replay_response returns Err (likely header reconstruction) and fix the capture/replay codec","Ensure repeated set-cookie headers are stored as a list and re-attached with HeaderValue::append on replay","Add a debug print of the captured struct when the expect fires"],"exampleFix":"// before\nlet reconstructed = replay_response(&captured).expect(\"a captured response must reconstruct\");\n// after\nlet reconstructed = replay_response(&captured)\n    .unwrap_or_else(|e| panic!(\"a captured response must reconstruct: {e:?}\"));","handlingStrategy":"try-catch","validationCode":"if captured.status.is_none() || captured.headers.is_empty() { panic!(\"capture looks empty before replay\"); }","typeGuard":"fn can_replay(c: &CapturedResponse) -> bool { c.status.is_some() && !c.body.is_empty() }","tryCatchPattern":"replay_response(&captured).unwrap_or_else(|e| panic!(\"a captured response must reconstruct: {e:?}\"))","preventionTips":["Round-trip tests for multi-valued headers whenever capture structs change","Assert set-cookie multiplicity explicitly in tests"],"tags":["rust","tests","http","round-trip"],"backgroundTag":"unexpected-response-shape","analyzedSha":"afd92843521ced2c6856b98ae4ea332e75102d88","analyzedAt":"2026-09-18T01:18:02.947Z","contentChangedAt":"2026-09-18T01:18:02.947Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}