Invalid value error from Storefront API

Solved

Invalid value error from Storefront API

ason-dev
Tourist
4 1 1

I'm building a Hydrogen store. I'm running into a storefront api error attempting to update a product's quantity with Remix's useFetcher. My code looks like this:

import {useState} from 'react';
import {Listbox} from '@headlessui/react';
import {CartForm} from '@shopify/hydrogen';
import {useFetcher} from '@remix-run/react';

export default function QuantityPicker({line}) {
  if (!line || typeof line?.quantity === 'undefined') return null;

  const fetcher = useFetcher();

  const {id: lineId, quantity, attributes, merchandise} = line;
  const {id: merchId} = merchandise;

  const [selected, setSelected] = useState(quantity);

  const buildFormInput = (qty) => ({
    action: CartForm.ACTIONS.LinesUpdate,
    inputs: [
      {
        id: lineId,
        merchandiseId: merchId,
        quantity: qty,
        attributes: attributes,
      },
    ],
  });

  return (
    <Listbox
      value={selected}
      onChange={(qty) => {
        if (qty === selected) {
          return;
        }
        fetcher.submit(
          {
            [CartForm.INPUT_NAME]: JSON.stringify(buildFormInput(qty)),
          },
          {method: 'POST', action: '/cart'},
        );
        setSelected(qty);
      }}
    >
      {/* listbox component options */}
    </Listbox>
  );
}

 

And this is the error I'm getting:

[h2:error:storefront.mutation] Variable $lines of type [CartLineUpdateInput!]! was provided invalid value - Request ID: 50a9b037-4794-4489-9b90-53981xxxxxxx

 

Can anyone tell what I might be getting wrong? I've gotten this to work in GraphiQL, but struggling to get it working in my store code.

 

Thanks for any suggestions

Accepted Solution (1)
ason-dev
Tourist
4 1 1

This is an accepted solution.

Thanks for the nudge in the right direction Scott, I'm new to GraphQL and though it seems obvious now, it hadn't occurred to me that the CartLinesUpdate mutation was sort of spelling out the shape of the inputs it needed. 

mutation cartLinesUpdate(
  $cartId: ID!
  $lines: [CartLineUpdateInput!]!
  $language: LanguageCode
  $country: CountryCode
) @inContext(country: null, language: null) {
  ...
}


I updated the shape of the inputs object that I am passing, and it's working now. Here's what it looks like now:

import {useState} from 'react';
import {Listbox} from '@headlessui/react';
import {CartForm} from '@shopify/hydrogen';
import {useFetcher} from '@remix-run/react';

export default function QuantityPicker({line}) {
  if (!line || typeof line?.quantity === 'undefined') return null;

  const fetcher = useFetcher();

  const {id: lineId, quantity, attributes, merchandise} = line;
  const {id: merchId} = merchandise;

  const [selected, setSelected] = useState(quantity);

  const buildFormInput = (qty) => ({
    action: CartForm.ACTIONS.LinesUpdate,
    inputs: {
      lines: [
        {
          attributes: attributes,
          id: lineId,
          merchandiseId: merchId,
          quantity: qty,
        },
      ],
    },
  });

  return (
    <Listbox
      value={selected}
      onChange={(qty) => {
        if (qty === selected) {
          return;
        }
        fetcher.submit(
          {
            [CartForm.INPUT_NAME]: JSON.stringify(buildFormInput(qty)),
          },
          {method: 'POST', action: '/cart'},
        );
        setSelected(qty);
      }}
    >
        {/* rest of listbox component */}
    </Listbox>
  );
}

 

 

View solution in original post

Replies 6 (6)

SBD_
Shopify Staff
1831 273 418

Hey @ason-dev 


What do you see when you log this piece?

 

{
    action: CartForm.ACTIONS.LinesUpdate,
    inputs: [
      {
        id: lineId,
        merchandiseId: merchId,
        quantity: qty,
        attributes: attributes,
      },
    ],
}

 

Are you able to provide a full request ID? I can take a look at the request in the logs.

Scott | Developer Advocate @ Shopify 

ason-dev
Tourist
4 1 1

Hi Scott, here's the output of logging that:

{
  "action":"LinesUpdate",
  "inputs":[{
    "id":"gid://shopify/CartLine/525cb323-9429-4094-8ec0-2d54ef1481d0?cart=c1-24d8df314b88afecf86410da54b9f9ce",
    "merchandiseId":"gid://shopify/ProductVariant/46243164225840",
    "quantity":2,
    "attributes":[{"key":"Case engraving","value":"John Doe"}]
  }]
}

 

And here's a full error message with a request ID:

[h2:error:storefront.mutation] Variable $lines of type [CartLineUpdateInput!]! was provided invalid value - Request ID: af30a7d0-4bb4-472e-a65c-5e9198f2daec

 

Thanks for looking into this!

SBD_
Shopify Staff
1831 273 418

Thanks @ason-dev - looking ok so far. Can I trouble you for one more request ID please? Our log retention period is only three days and I've just come back to this. Sorry and thanks!

Scott | Developer Advocate @ Shopify 

ason-dev
Tourist
4 1 1

No problem, here's a fresh one.

 

[h2:error:storefront.mutation] Variable $lines of type [CartLineUpdateInput!]! was provided invalid value - Request ID: ec2d588f-b621-40c8-b065-69ebda63aea2

 

SBD_
Shopify Staff
1831 273 418

Thanks @ason-dev! On our end, the mutation/variables look like this:

 

mutation cartLinesUpdate(
  $cartId: ID!
  $lines: [CartLineUpdateInput!]!
  $language: LanguageCode
  $country: CountryCode
) @inContext(country: null, language: null) {
  cartLinesUpdate(cartId: null, lines: null) {
    cart {
      ...CartApiMutation
    }
    errors: userErrors {
      ...CartApiError
    }
  }
}
fragment CartApiMutation on Cart {
  id
  totalQuantity
}
fragment CartApiError on CartUserError {
  message
  field
  code
}

// Variables:
{
  cartId: "gid://shopify/Cart/c1-24d8df314b88afecf86410da54b9f9ce",
  country: "US",
  language: "EN",
}

 

Note the `lines` variable is missing.

 

Hope this helps you debug. If you get stuck I'm happy to take a look at your application code.

Scott | Developer Advocate @ Shopify 

ason-dev
Tourist
4 1 1

This is an accepted solution.

Thanks for the nudge in the right direction Scott, I'm new to GraphQL and though it seems obvious now, it hadn't occurred to me that the CartLinesUpdate mutation was sort of spelling out the shape of the inputs it needed. 

mutation cartLinesUpdate(
  $cartId: ID!
  $lines: [CartLineUpdateInput!]!
  $language: LanguageCode
  $country: CountryCode
) @inContext(country: null, language: null) {
  ...
}


I updated the shape of the inputs object that I am passing, and it's working now. Here's what it looks like now:

import {useState} from 'react';
import {Listbox} from '@headlessui/react';
import {CartForm} from '@shopify/hydrogen';
import {useFetcher} from '@remix-run/react';

export default function QuantityPicker({line}) {
  if (!line || typeof line?.quantity === 'undefined') return null;

  const fetcher = useFetcher();

  const {id: lineId, quantity, attributes, merchandise} = line;
  const {id: merchId} = merchandise;

  const [selected, setSelected] = useState(quantity);

  const buildFormInput = (qty) => ({
    action: CartForm.ACTIONS.LinesUpdate,
    inputs: {
      lines: [
        {
          attributes: attributes,
          id: lineId,
          merchandiseId: merchId,
          quantity: qty,
        },
      ],
    },
  });

  return (
    <Listbox
      value={selected}
      onChange={(qty) => {
        if (qty === selected) {
          return;
        }
        fetcher.submit(
          {
            [CartForm.INPUT_NAME]: JSON.stringify(buildFormInput(qty)),
          },
          {method: 'POST', action: '/cart'},
        );
        setSelected(qty);
      }}
    >
        {/* rest of listbox component */}
    </Listbox>
  );
}