Skip to content

Flutter JSON errorFlutter: “‘_InternalLinkedHashMap<String, dynamic>’ is not a subtype of type ‘List<dynamic>’”

Parsing an API response throws type ‘_InternalLinkedHashMap<String, dynamic>’ is not a subtype of type ‘List<dynamic>’ (newer Dart prints _Map<String, dynamic>). The code treats the decoded JSON as a list, but the server sent an object: often the list is wrapped in a key such as data or results, or the server returned an error object instead.

Short answer

Print response.body and look at the first character. If it is {, the top level is a map: read the list from its key, for example (json['data'] as List). Check the status code before parsing, because error responses are usually objects. Then map each item with fromJson.

Why the JSON isn’t the list you expected, and the fix

  1. 01

    The list is wrapped in an object

    “Unfortunately, jsonDecode() returns a dynamic, meaning that you do not know the types of the values until runtime.” Flutter, JSON and serialization

    jsonDecode gives you whatever shape the server sent. Many APIs send {"data": [...], "page": 1}, which decodes to a Map; take the list out of it, then convert each item.

    final json = jsonDecode(response.body) as Map<String, dynamic>;
    final items = (json['data'] as List)
        .map((e) => Product.fromJson(e as Map<String, dynamic>))
        .toList();
  2. 02

    The server returned an error object

    “If the server does not return an OK response with a status code of 200, then throw an exception.” Flutter, Fetch data from the internet

    A 401, 404 or 500 usually comes back as {"error": "..."} even when the success response is a list. Check the status code first, so you parse only the shape you expect.

    if (response.statusCode != 200) {
      throw Exception('Request failed: ${response.statusCode} ${response.body}');
    }
    final list = jsonDecode(response.body) as List;
  3. 03

    A single item where the model expects a list

    An endpoint such as /products/42 returns one object. Use fromJson on the map directly instead of mapping over it, or call the list endpoint.

    final product = Product.fromJson(
      jsonDecode(response.body) as Map<String, dynamic>,
    );

Checked against the vendor’s docs on : Flutter: JSON and serialization; Flutter cookbook: Fetch data from the internet.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Flutter “type Null is not a subtype of type String” · Flutter “SocketException: Failed host lookup” · Flutter “Bad state: No element” · Flutter “Looking up a deactivated widget’s ancestor is unsafe”

Questions

More on this error

It says List<dynamic> is not a subtype of Map<String, dynamic>. Same fix?

The mirror case: the server sent a list and the code expects one object. Cast to List and map each element with fromJson.

What about List<dynamic> is not a subtype of List<String>?

jsonDecode makes every list a List<dynamic>. Convert it with List<String>.from(json['tags']) or (json['tags'] as List).cast<String>().

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.