Http.Error.BadStatus loses response body on non-success HTTP statuses
0 reputation · 22 Jul 2022, 07:20 UTC
0 reputation · 22 Jul 2022, 07:20 UTC
Retrieve the server‑sent response body when an Elm http request results in a non‑2xx status, so that error messages returned as JSON can be decoded and displayed.
Http.Error.BadStatus constructor carries only the integer status code; the response body, headers, and raw payload are not attached.expectJson and expectString are invoked only for successful responses, leaving server error bodies inaccessible through the normal Http path.BadStatus without abandoning the built‑in success/failure routing, or if users must always drop to lower‑level APIs like expectStringResponse.BadStatus values?expectJson/expectString flow to expectStringResponse for handling non‑2xx responses?Http.Error union type?34275 reputation · 22 Jul 2022, 14:31 UTC
The Http.Error.BadStatus constructor cannot be configured or extended to include the response body. To retrieve the server-sent body during a non-2xx response, you must use Http.expectStringResponse. This shifts the responsibility of status validation and decoding from the library to your application logic, allowing you to capture the raw payload and decode it using Json.Decode.
In the standard elm/http flow, helpers like expectJson only execute the provided decoder if the server returns a 2xx status code. If the status is non-success, the library short-circuits and returns a BadStatus containing only the integer code, discarding the body to maintain a strict type definition for Http.Error.
expectJson. You must manually handle the Result, check the status code (if using a response-aware helper), and manage the decoding process for both success and error cases.To preserve the original Http.Error while adding decoded error details, define a custom error union type:
type MyError
= NetworkError Http.Error
| ServerError Int MyErrorPayload
| DecodeError String
-- Use expectStringResponse to get the raw body
-- Then manually decode based on the status code
case result of
Ok bodyStr ->
case Decode.decodeString errorDecoder bodyStr of
Ok payload -> Err (ServerError 400 payload)
Err _ -> Ok (Decode.decodeString successDecoder bodyStr)
Err err ->
Err (NetworkError err)
Verification Steps:
{"error": "Invalid input"}).expectJson with expectStringResponse.Ok branch of the result now contains the JSON string instead of triggering a BadStatus error.Json.Decode logic to confirm the payload is recoverable.Does your server consistently return application/json for all non-2xx statuses? If the server occasionally returns HTML error pages (e.g., from a load balancer or 500 Internal Server Error), you must include a fallback in your decoding logic to prevent the application from crashing or showing a generic "Decode Error" when the body is not JSON.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.