Graphql_flutter mutation running on playground doesn't work on running device/emulator

382 views Asked by At

During my project development, I'm using flutter with graphql, for testing purpose tried mutation on playground and passed the test, but on device and emulator getting error response with 5xx, I know this is "server side" error but tested same mutation from our webpage and it is working too. Beside with flutter, I am using following packages:

  • equatable: ^1.2.5
  • gql: ^0.12.4
  • graphql: ^4.0.0
  • graphql_flutter: ^4.0.1
  • json_annotation: ^3.1.1
  • meta: ^1.3.0
  • artemis: ^6.18.4
  • build_runner: ^1.11.1
  • json_serializable: ^3.5.1

Till now on this project, I run almost 10 mutations successfully with this file syntax:

  • myproject/
    • graphql/
      • queries/
        • register.graphql -> running well
        • createOffer.graphql -> getting 500 error
      • schema.graphql
    • lib/
      • models/
        • ...generatedModels here..
      • views/
        • register.dart
        • createOffer.dart

register.graphql

mutation signUp(
    $company_name:String!,
    $email: String!,
    $firstname: String!,
    $lastname: String!,
    $phone: String!,
    $tin_ein_number: String!,
) {
    createShipperUser(
        company_name: $company_name,
        email: $email,
        firstname: $firstname,
        lastname: $lastname,
        phone: $phone,
        tin_ein_number: $tin_ein_number,
    ) {
        id
    }
}

register.dart

Widget buildFormBody(BuildContext context) {
    return Mutation(
      options: MutationOptions(
        document: SignUpMutation().document,
        onCompleted: (dynamic resultData) {
          if (resultData != null) {
            onRegistered();
          }
        },
        if (e.linkException != null) {
            showSnackbar(context,
                'Something went wrong, please check your network connection and try again.');
            return;
        }
        final validationErrors = findValidationErrors(
            e.graphqlErrors,
            [
              'firstname',
              'lastname',
              'email',
              'phone',
              'tin_ein_number',
              'company_name',
            ],
          );
          if (validationErrors.isNotEmpty) {
            setState(() {
              firstnameError = validationErrors['firstname'];
              surnameError = validationErrors['lastname'];
              emailError = validationErrors['email'];
              phoneError = validationErrors['phone'];
              if (isTin) {
                einError = null;
                tinError = validationErrors['tin_ein_number'];
              } else {
                einError = validationErrors['tin_ein_number'];
                tinError = null;
              }
              companyError = validationErrors['company_name'];
            });
            //TODO text
            showSnackbar(context, 'Please check entered fields');
          } else if (e.graphqlErrors.isNotEmpty) {
            showSnackbar(
                context, e.graphqlErrors[0].message ?? 'Something went wrong');
          } else {
            showSnackbar(context, 'Something went wrong');
          }
          builder: (runMutation, result) {
           isLoading = result.isLoading;
           return Form( 
             ElevatedButton(
               onPressed: () => onSubmitTap(runMutation),
               child: Text(
                              'Submit',
                              style: TextStyle(
                                  fontSize: 16, fontWeight: FontWeight.w700),
               ),
             )         
           );
        
  void onSubmitTap(RunMutation runMutation) {
    hideKeyboard();
    if (isLoading) {
      return;
    }

    if (formKey.currentState.validate()) {
      formKey.currentState.save();

      setState(() {
        savedPhone = getPhoneMask(savedPhone);
      });

      runMutation(SignUpArguments(
        company_name: savedCompany,
        email: savedEmail,
        phone: savedPhone,
        tin_ein_number: isTin ? 'tin_$savedTin' : 'ein_$savedEin',
        firstname: savedFirstname,
        lastname: savedSurname,
      ).toJson());
    }
  }

And following are mutation getting 500 error.

createOffer.graphql

Mutation(
                      options: MutationOptions(
                        document: CreateShipmentMutation().document,
                        errorPolicy: ErrorPolicy.all,
                        update: (GraphQLDataProxy cache, QueryResult result) {
                          if (result.hasException) {
                            print(result.exception);
                          }
                        },
                        onCompleted: (dynamic resultData) {
                          if (resultData != null) {
                            print('completed');
                            print(resultData);
                            // onCreated();
                          }
                        },
                        onError: (e) {
                          if (e.linkException != null) {
                            showSnackbar(context,
                                'Something went wrong, please check your network connection and try again.');
                            return;
                          }

                          if (e.graphqlErrors.isNotEmpty) {
                            debugPrint(e.graphqlErrors.toString(),
                                wrapWidth: 1024);
                          } else {
                            showSnackbar(context, 'Something went wrong');
                          }
                        },
                      ),
                      builder: (runMutation, result) {
                        isLoading = result.isLoading;
                        return Card(
                          child: ElevatedButton(
                                    onPressed: () => onReviewTap(runMutation),
                                    style: ElevatedButton.styleFrom(
                                        padding:
                                            EdgeInsets.symmetric(vertical: 14)),
                                    child: AnimatedSwitcher(
                                      duration: Duration(milliseconds: 150),
                                      child: result.isLoading
                                          ? Theme(
                                              data: Theme.of(context).copyWith(
                                                  accentColor: Colors.white),
                                              child:
                                                  const ProgressIndicatorSmall(),
                                            )
                                          : Text(
                                              'Review Shipment',
                                              style: TextStyle(
                                                  fontSize: 16,
                                                  fontWeight: FontWeight.w700),
                                            ),
                                    ),
                                  ),
                        );

void onReviewTap(RunMutation runMutation) {
    final acces = accessories
        .map((accessory) {
          if (accessory.isChecked) {
            return accessory.enumType;
          }
        })
        .where((element) => element != null)
        .toList();
    final stops = isMultipleStops ? items : p2pitems;

    hideKeyboard();
    if (isLoading) {
      return;
    }

    runMutation(CreateShipmentArguments(
      input: OfferInput(
        openPrice: 30,
        shipment: CreateShipmentInput(
          requestedTruckTypes: [
            TruckTypesEnum.dryVan,
          ],
          accessorials: [
            AccessorialsEnum.twicRequired,
            AccessorialsEnum.ppe,
          ],
          trailer: TrailerInput(
            temperatureMax: 0,
            temperatureMin: 0,
            temperatureUnit: TemperatureUnitsEnum.f,
          ),
          items: [
            ItemInput(
              description: "Items description",
              weight: WeightInput(
                weight: 100,
                weightUnit: WeightUnitTypesEnum.lb,
              ),
              units: UnitInput(
                unitCount: 0,
                unitType: ItemUnitTypesEnum.units,
              ),
              handlingPiece: HandlingPieceInput(
                pieceCount: 0,
                pieceType: ItemPieceTypesEnum.pallets,
              ),
            ),
          ],
          shortName: "Dem23",
          loadDescription: "adhjahsdhajsdj",
          routeDistanceMiles: 0.0,
          routeDurationMinutes: 0,
          stops: [
            CreateStopInput(
                appointmentType: AppointmentTypesEnum.alreadyMade,
                startTime: "2021-05-03T00:00:00+02:00",
                type: StopTypesEnum.pickup,
                loadingType: LoadingTypesEnum.live,
                locationInput: LocationInput(
                  locationName: "HOUSTON",
                  coordinates:
                      CoordinatesInput(lat: 29.608774, lng: -95.516164),
                  address: AddressInput(
                      full:
                          "14810 Fairway Pines Dr, Missouri City, TX 77489, USA",
                      city: "Missouri City",
                      state: "TX",
                      street: "Fairway Pines Drive",
                      streetNumber: 14810),
                  operationalContact: ContactInput(
                      contactName: "mr contact",
                      email: "[email protected]",
                      phoneNumber: "862615986",
                      notes: "notes lorem ipsum"),
                  schedulingContact: ContactInput(
                      contactName: "mr contact",
                      email: "[email protected]",
                      phoneNumber: "862615986",
                      notes: "notes lorem ipsum"),
                )),
            CreateStopInput(
              appointmentType: AppointmentTypesEnum.toBeMade,
              startTime: "2021-05-14T05:13:30+00:00",
              endTime: "2021-04-27T17:35:00+00:00",
              type: StopTypesEnum.dropoff,
              loadingType: LoadingTypesEnum.live,
              locationInput: LocationInput(
                locationName: "COSTCO WHO,WEBSTER,TX,USA",
                coordinates: CoordinatesInput(lat: 29.533604, lng: -95.136843),
                address: AddressInput(
                  full: "1310 Jasmine St, Webster, TX 77598, USA",
                  city: "Webster",
                  state: "TX",
                  street: "Jasmine Street",
                  streetNumber: 1310,
                ),
                operationalContact: ContactInput(
                    contactName: "mr contact",
                    email: "[email protected]",
                    phoneNumber: "862615986",
                    notes: "notes lorem ipsum"),
                schedulingContact: ContactInput(
                    contactName: "mr contact",
                    email: "[email protected]",
                    phoneNumber: "862615986",
                    notes: "notes lorem ipsum"),
              ),
            ),
          ],
        ),
      ),
    ).toJson());

Following are the hardcodes on playground for createOffer:

mutation CreateShipment (
  $input: OfferInput!
) {
  createOffer(input: $input){
    uuid
    shipper_id
  }
}
#variables
{
  "input": {
    "open_price": 30,
    "shipment": {
      "requested_truck_types": [
        "DRY_VAN"   
      ],
      "accessorials": [
        "TWIC_REQUIRED",
        "SHIPPER_REQUIRES_MASK_GLOVES",
        "PPE"
      ],
      "items": [
        {
          "description": "Items description",
          "handling_piece": {
            "piece_type": "PALLETS",
            "piece_count": 0
          },
          "units": {
            "unit_type": "UNITS",
            "unit_count": 0
          },
          "weight": {
            "weight": 100,
            "weight_unit": "LB"
          }
        }
      ],
      "trailer": {
        "temperature_max": 0,
        "temperature_min": 0,
        "temperature_unit": "F"
      },
      "short_name": "Dem",
      "load_description": "load descriotajj adaksdjad",
      "route_distance_miles": 0.0,
      "route_duration_minutes": 0,
      "stops": [
        {
          "appointment_type": "ALREADY_MADE",
          "start_time": "2021-05-03T00:00:00+02:00",
          "type": "PICKUP",
          "loading_type": "LIVE",
          "location_input": {
            "location_name": "HOUSTON",
            "coordinates": {
              "lat": 29.608774,
              "lng": -95.516164
            },
            "address": {
              "full": "14810 Fairway Pines Dr, Missouri City, TX 77489, USA",
              "city": "Missouri City",
              "state": "TX",
              "street": "Fairway Pines Drive",
                    "street_number" :14810
            },
            "operational_contact": {
              "contact_name" : "mr contact",
                    "email" : "[email protected]",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            },
            "scheduling_contact": {
              "contact_name" : "mr contact",
                    "email" : "[email protected]",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            }
          }
        },
        {
          "appointment_type": "TO_BE_MADE",
          "start_time": "2021-05-14T05:13:30+00:00",
          "end_time": "2021-04-27T17:35:00+00:00",
          "type": "DROPOFF",
          "loading_type": "LIVE",
          "location_input": {
            "location_name": "COSTCO WHO,WEBSTER,TX,USA",
            "coordinates": {
              "lat": 29.533604,
              "lng": -95.136843
            },
            "address": {
              "full": "1310 Jasmine St, Webster, TX 77598, USA",
              "city": "Webster",
              "state": "TX",
              "street": "Jasmine Street",
                    "street_number" :1310
            },
            "operational_contact": {
              "contact_name" : "mr contact",
                    "email" : "[email protected]",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            },
            "scheduling_contact": {
              "contact_name" : "mr contact",
                    "email" : "[email protected]",
                    "phone_number" : "862615986",
                  "notes" : "notes lorem ipsum"
            }
          }
        }
      ]
    }
  }
}

and response

{
  "data": {
    "createOffer": {
      "uuid": "933eee0a-8x82-46d6-xxx-018xxxxxxx40",
      "shipper_id": "3"
    }
  },
  "extensions": {
    "lighthouse_subscriptions": {
      "version": 1,
      "channel": null,
      "channels": []
    }
  }
}

to check if working graphql validation, I made mistake on datetime in starttime/endtime and get this:

{
  "errors": [
    {
      "message": "Variable \"$input\" got invalid value {\"open_price\":30,\"shipment\":{\"requested_truck_types\":[\"DRY_VAN\"],\"accessorials\":[\"TWIC_REQUIRED\",\"SHIPPER_REQUIRES_MASK_GLOVES\",\"PPE\"],\"items\":[{\"description\":\"Items description\",\"handling_piece\":{\"piece_type\":\"PALLETS\",\"piece_count\":0},\"units\":{\"unit_type\":\"UNITS\",\"unit_count\":0},\"weight\":{\"weight\":100,\"weight_unit\":\"LB\"}}],\"trailer\":{\"temperature_max\":0,\"temperature_min\":0,\"temperature_unit\":\"F\"},\"short_name\":\"Dem\",\"load_description\":\"load descriotajj adaksdjad\",\"route_distance_miles\":0,\"route_duration_minutes\":0,\"stops\":[{\"appointment_type\":\"ALREADY_MADE\",\"start_time\":\"2021-05-03T00:00:00\",\"type\":\"PICKUP\",\"loading_type\":\"LIVE\",\"location_input\":{\"location_name\":\"HOUSTON\",\"coordinates\":{\"lat\":29.608774,\"lng\":-95.516164},\"address\":{\"place_id\":\"EjQxNDgxMCBGYWlyd2F5IFBpbmVzIERyLCBNaXNzb3VyaSBDaXR5LCBUWCA3NzQ4OSwgVVNB\",\"full\":\"14810 Fairway Pines Dr, Missouri City, TX 77489, USA\",\"city\":\"Missouri City\",\"state\":\"TX\",\"street\":\"Fairway Pines Drive\",\"street_number\":14810},\"operational_contact\":{\"contact_name\":\"mr contact\",\"email\":\"[email protected]\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"},\"scheduling_contact\":{\"contact_name\":\"mr contact\",\"email\":\"[email protected]\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"}}},{\"appointment_type\":\"TO_BE_MADE\",\"start_time\":\"2021-05-14T05:13:30+00:00\",\"end_time\":\"2021-04-27T17:35:00+00:00\",\"type\":\"DROPOFF\",\"loading_type\":\"LIVE\",\"location_input\":{\"location_name\":\"COSTCO WHO,WEBSTER,TX,USA\",\"coordinates\":{\"lat\":29.533604,\"lng\":-95.136843},\"address\":{\"full\":\"1310 Jasmine St, Webster, TX 77598, USA\",\"city\":\"Webster\",\"state\":\"TX\",\"street\":\"Jasmine Street\",\"street_number\":1310},\"operational_contact\":{\"contact_name\":\"mr contact\",\"email\":\"[email protected]\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"},\"scheduling_contact\":{\"contact_name\":\"mr contact\",\"email\":\"[email protected]\",\"phone_number\":\"862615986\",\"notes\":\"notes lorem ipsum\"}}}]}}; Expected type DateTimeTz at value.shipment.stops[0].start_time; \"Data missing\"",
      "extensions": {
        "category": "graphql"
      },
      "locations": [
        {
          "line": 1,
          "column": 25
        }
      ]
    }
  ],
  "extensions": {
    "lighthouse_subscriptions": {
      "version": 1,
      "channel": null,
      "channels": []
    }
  }
}

which means all fields I was sending are correct, I think. Maybe requested field types are accepting valid input types from me but causing error while working/parsing them, I don't know, I am struggling with this for almost a week and as you can see two hardcodes (flutter/playground) are the same. My textfields and other inputs are ready but I can't run hardcode first of all :/ btw this is not expired token, for that I got unathorized action error.

1

There are 1 answers

0
Atabek Kadirow On

Finally we could solve this issue. Issue was occuring on backend while parsing data come from my side. This was the flow of data:

  • user enters data
  • before mutation, flutter parsing data and graphql_flutter mutate
  • then, backend(in our case, php) does fields validation if all are ok, next, if not send validation errors to the client side.
  • after all, server starting storing data on db (here is the key point)

My issue was occuring on last stage, unnecessary model property was sent null, we get to know this by reading logs in laravel.log, so removing that field and migrate db, finally download and using "new" schema.graphql from playground resolved this issue. I hope this will be helpful later :)