Skip to content

Improve DioException detail when ResponseType.json receives HTML responses #2489

@thanhle1547

Description

@thanhle1547

Description

When Options.responseType is set to ResponseType.json, Dio attempts to decode the response body using the default transformer (FusedTransformer). However, if a server-side crash occurs (e.g., a 500 Internal Server Error), the server often returns a standard HTML error page while maintaining a Content-Type: application/json header.

Because the body is HTML (starting with <), jsonDecode throws: FormatException: Unexpected character (at offset 0)

Currently, when this happens, the resulting DioException makes it difficult to retrieve the original HTML string. This is a major pain point for debugging, as the HTML body usually contains the stack trace or error reason from the web server.

Current Behavior

  1. Request is made with ResponseType.json.
  2. Server responds with a 500 Error and an HTML body, but still sends Content-Type: application/json.
  3. FusedTransformer fails to parse the HTML as JSON.
  4. A FormatException is thrown.
  5. The developer receives a DioException, but response is null.

Expected Behavior

Even if JSON decoding fails, the DioException should:

  • Capture the raw response body.
  • Populate DioException.response.data with the original String.
  • Allow the developer to see the server's HTML output to diagnose the 500 error.

Solution Brainstorm (Minimal Idea)

The FusedTransformer.transformResponse should be modified to catch FormatException during JSON decoding and fallback to the raw string.

  1. For the Fast Path
try {
  return await _fastUtf8JsonDecode(options, responseBody);
} catch (e) {
  // If the response is not JSON and no custom decoder was specified,
  // assume it is an utf8 string
  final responseBytes = await consolidateBytes(responseBody.stream);
  return utf8.decode(responseBytes, allowMalformed: true);
}
  1. For the Slow Path
if (isJsonContent && decodedResponse != null) {
  try {
    return jsonDecode(decodedResponse);
  } catch (e) {
    // If the custom decoder produced a string that isn't valid JSON,
    // return the raw string so it's accessible in DioException.response.data
    return decodedResponse;
  }
}

The Challenge:

While returning the raw string solves the problem of accessing the data, the developer should still be notified that the response was not valid JSON. We need a solution that preserves the raw data without losing the 'Invalid JSON' error state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    s: featureThis issue indicates a feature request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions