'Flutter: Dart Error: RangeError (index): Invalid value: Only valid value is 0: 1

Hey guys I am new to Flutter and trying to build a variation selector for an eCommerce application. I am getting this error while trying to build a size variation widget for the size-color variation. It works for size only or color only variation. This is the error RangeError (index): Invalid value: Only valid value is 0: 1.

Also, when I print the length of the array, I am getting the value 1.

The idea is to show the available sizes when someone clicks on a color that gets displayed without any issues. but while trying to show the size, facing this error.

This is the code

///size widget
class SelectSizeWidget extends StatefulWidget {
  SelectSizeWidget({
    Key? key,
  }) : super(key: key);

  @override
  _SelectSizeWidgetState createState() => _SelectSizeWidgetState();
}

class _SelectSizeWidgetState extends State<SelectSizeWidget> {
  @override
  Widget build(BuildContext context) {
    return Consumer<ProductController>(
      builder: (_,model,__) {
        return Wrap(
          spacing: 8,
          runSpacing: 8,
          children: List.generate((model.sizeColour.isNotEmpty) ? model.ss.length : model.size.length , (index) {
            if(model.sizeColour.isNotEmpty) {
              if(model.selectedColour != null || model.selectedColour != ""){
              var _res = model.sizeColour
                  .where((element) =>
                      element.var2!.toUpperCase() == model.selectedColour)
                  .toList();
              var _size = _res[index];
              return buildSize(_size);

            } else {
                var _res = model.sizeColour.toList();
                var _size = _res[index];
                return buildSize(_size);

              }
          } else if (model.size.isNotEmpty) {
              var _size = model.size[index];
              return buildSize(_size);
            }else if(model.materialSize.isNotEmpty){
              var _res = model.materialSize.where((element) =>
              element.var1.toUpperCase() == model.selectedMaterial)
                  .toList();
              var _size = _res[index];
              return buildSize(_size);
            }else{
              return SizedBox.shrink();
            }
          }),
        );
      }
    );
  }

  SizedBox buildSize(Variant size) {
    return SizedBox(
      height: 38,
      child: RawChip(
        label: Text(size.var1),
        labelStyle: TextStyle(color: Theme.of(context).hintColor),
        padding: EdgeInsets.symmetric(horizontal: 7, vertical: 7),
        backgroundColor: Theme.of(context).focusColor.withOpacity(0.05),
        selectedColor: Theme.of(context).focusColor.withOpacity(0.2),
        selected: size.varId == context.read<ProductController>().selectedVariation,
        shape: StadiumBorder(side: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.05))),
        onSelected: (bool value) {
          context.read<ProductController>().setSize(size.varId);
        },
      ),
    );
  }
}

Productcontroller - for detail

List<Variant> size = [];
List<Variant> colour = [];
List<Variant> sizeColour = [];
List<String> ss = [];
List<String> cc = [];


Future<bool> getProductDetails({required String slug}) async {

  final val = await ApiProvider().getProductDetails(slug: slug);
  if (val.statusCode == 200 || val.statusCode == 201) {
    product = productDetailsResponseFromJson(jsonEncode(val.data));

    /// variation
    if (product!.variants) {
      clearAll();
      List<Map<int, Set<String>>> sc = [];
      List<String> s = [];
      List<String> c = [];

      selectedVariation = product!.prdtVari.first.id;
      for (var each in product!.prdtVari) {
        var _var = each.variation.toLowerCase();
        
        if (_var == 'colour') {
          colour.add(Variant(
              varId: each.id,
              var1: each.variationTypes.first.name,
              typeMap1: each.variationTypes.first.typeMap));
          c.add(each.variationTypes.first.name);
          notifyListeners();
        } else if (_var == 'size') {
          size.add(Variant(
              varId: each.id,
              var1: each.variationTypes.first.name,
              typeMap1: each.variationTypes.first.typeMap));
          s.add(each.variationTypes.first.name);
          notifyListeners();
        } else if (_var == 'size-colour') {
          sc.add({
            each.id: {
              each.variationTypes.first.name,
              each.variationTypes.last.name
            }
          });
          sizeColour.add(Variant(
              varId: each.id,
              var1: each.variationTypes.first.name,
              typeMap1: each.variationTypes.first.typeMap,
              var2: each.variationTypes.last.name,
              typeMap2: each.variationTypes.last.typeMap));
          s.add(each.variationTypes.first.name);
          c.add(each.variationTypes.last.name);
          notifyListeners();
        } 
      }
      ss = s.toSet().toList();
      cc = c.toSet().toList();

      if(cc.isNotEmpty){
        if(product!.prdtVari.first.variation.toLowerCase() == "colour"){
          selectedColour = colour.where((element) => element.varId == selectedVariation!).first.var1.toUpperCase();
        } else if(product!.prdtVari.first.variation.toLowerCase() == "size-colour") {
          selectedColour = sizeColour.where((element) => element.varId == selectedVariation!).first.var2!.toUpperCase();
        }
      };
      notifyListeners();
    }
    isLoading = false;
    notifyListeners();
    return true;
  } else {
    isLoading = false;
    notifyListeners();
    return false;
  }
}

API model

// To parse this JSON data, do
//
//     final productDetailsResponse = productDetailsResponseFromJson(jsonString);

import 'dart:convert';

ProductDetailsResponse productDetailsResponseFromJson(String str) => ProductDetailsResponse.fromJson(json.decode(str));

String productDetailsResponseToJson(ProductDetailsResponse data) => json.encode(data.toJson());


class ProductDetailsResponse {
  ProductDetailsResponse({

    required this.category,
    required this.title,
    required this.variants,
    required this.slug,
    required this.averageReview,
    required this.countReview,
    required this.productDetailsInfo,
    required this.prdtImg,
    required this.prdtVari,
  });

  int category;
  String title;
  bool variants;
  String slug;
  double averageReview;
  int countReview;
  ProductDetailsInfo productDetailsInfo;
  List<ProductDetailsImages> prdtImg;
  List<ProductDetailsVariation> prdtVari;

  factory ProductDetailsResponse.fromJson(Map<String, dynamic> json) => ProductDetailsResponse(

    category: json["category"],
    title: json["title"],
    variants: json["var"],
    slug: json["slug"],
    averageReview: json["rating"],
    countReview: json["rCount"],
    productDetailsInfo: ProductDetailsInfo.fromJson(json["prdtInfo"]),
    prdtImg: List<ProductDetailsImages>.from(json["prdtImg"].map((x) => ProductDetailsImages.fromJson(x))),
    prdtVari: List<ProductDetailsVariation>.from(json["prdtVari"].map((x) => ProductDetailsVariation.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {

    "category": category,
    "title": title,
    "var": variants,
    "slug": slug,
    "rating": averageReview,
    "rCount": countReview,
    "prdtInfo": productDetailsInfo.toJson(),
    "prdtImg": List<dynamic>.from(prdtImg.map((x) => x.toJson())),
    "prdtVari": List<dynamic>.from(prdtVari.map((x) => x.toJson())),
  };
}

class ProductDetailsImages {
  ProductDetailsImages({
    required  this.id,
    required  this.images,
    required  this.cover,
  });

  int id;
  String? images;
  bool cover;

  factory ProductDetailsImages.fromJson(Map<String, dynamic> json) => ProductDetailsImages(
    id: json["id"],
    images: json["images"],
    cover: json["cover"],
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "images": images,
    "cover": cover,
  };
}

class ProductDetailsInfo {
  ProductDetailsInfo({
    required  this.brand,
    required  this.mrp,
    required  this.price,
    required  this.inStock,
    required  this.desc,
    required  this.shipCost,
    required  this.condition,
  });

  String? brand;
  double mrp;
  double price;
  String inStock;
  String desc;
  double? shipCost;
  String condition;

  factory ProductDetailsInfo.fromJson(Map<String, dynamic> json) => ProductDetailsInfo(

    brand: json["brd"],
    mrp: json["mrp"],
    price: json["price"],
    inStock: json["iStock"],
    desc: json["desc"],
    shipCost: json["shCost"],
    condition: json["con"],

  );

  Map<String, dynamic> toJson() => {
    "brand": brand,
    "mrp": mrp,
    "price": price,
    "iStock": inStock,
    "desc": desc,
    "shCost": shipCost,
    "con": condition,

  };
}

class ProductDetailsVariation {
  ProductDetailsVariation({
    required this.id,
    required this.variation,
    required this.mrp,
    required this.price,
    required this.inStock,
    required this.images,
    required this.variationTypes,
  });

  int id;
  String variation;
  double mrp;
  double price;
  String inStock;
  List<ProductDetailsImages> images;
  List<ProductDetailsVariationType> variationTypes;

  factory ProductDetailsVariation.fromJson(Map<String, dynamic> json) => ProductDetailsVariation(
    id: json["id"],
    variation: json["vAtion"],
    mrp: json["mrp"],
    price: json["price"],
    inStock: json["iStock"],
    images: List<ProductDetailsImages>.from(json["imgs"].map((x) => ProductDetailsImages.fromJson(x))),
    variationTypes: List<ProductDetailsVariationType>.from(json["vTypes"].map((x) => ProductDetailsVariationType.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "vAtion": variation,
    "mrp": mrp,
    "price": price,
    "iStock": inStock,
    "imgs": List<dynamic>.from(images.map((x) => x.toJson())),
    "vTypes": List<dynamic>.from(variationTypes.map((x) => x.toJson())),
  };
}

class ProductDetailsVariationType {
  ProductDetailsVariationType({
    required  this.id,
    required  this.name,
    required this.typeMap,
  });
  int id;
  String name;
  String typeMap;

  factory ProductDetailsVariationType.fromJson(Map<String, dynamic> json) => ProductDetailsVariationType(
    id: json["id"],
    name: json["name"],
    typeMap: json["tMap"],
  );

  Map<String, dynamic> toJson() => {
    "id": id,
    "name": name,
    "tMap": typeMap,
  };
}

Thanks



Solution 1:[1]

List.generate is using model.ss.length or model.size.length to generate your list like you instructed on this line

List.generate((model.sizeColour.isNotEmpty) ? model.ss.length : model.size.length , (index) {

It means index <= model.ss.length-1 or index <= model.size.length-1. Then you did

var _res = model.sizeColour.where((element) => element.var2!.toUpperCase() == model.selectedColour).toList();

So if var _size = _res[index] throw RangeError it means _res.length < model.ss.length-1 or _res.length < model.size.length-1 but it should be equal, so the solution is to make sure the 3 arrays have the same length.

Solution 2:[2]

Try replacing the 'or' with 'and'

if(model.selectedColour != null && model.selectedColour != "")

Since you used or it is always true if either of the condition is met. So even it's empty that variable was assigned with empty value.

Solution 3:[3]

Error often happen when you render data in list but you hasn't data you try check null in code because you not have controller call api or data any where

  • you can check line code has "if" ...
  • check length of list > 0
  • "var _size = _res[index];" maybe index null

Solution 4:[4]

I could not read all the code and test it, but I got that error before. When? for example,

    List<String> myList = [1 , 2 ,3 ,4];

child : ListView(
children: [
  Text("${mylist[0]}"),
  Text("${mylist[1]}"),
  Text("${mylist[2]}"),
  Text("${mylist[3]}"),
  Text("${mylist[4]}"),
]
) ;

so you have four items in the list which mean your index will be just until 3 if you add more than the items in the list it will show that error. I hope I was able to explain.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Kaushik Chandru
Solution 3 Otis
Solution 4 Mohammed Fouad