Solved

Fail to pass variables to metafieldsSet mutation in Shopify Api Node js Grahql client?

yiuhoward
Tourist
3 1 2


I was trying to use the metafieldsSet mutation to update metafields through GraphQL Admin API with the following code:

const client = new Shopify.Clients.Graphql(
		process.env.SHOP,
		process.env.PASSWORD
	)
	try {
		const metafields = await client.query({
			data: `mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {
				metafieldsSet(metafields: $metafields) {
					userErrors {
						field
						message
					}
					metafields {
						key
						value
					}
				}
			}			
			`,
			query: {
				metafields: [
					{
						key: 'cb_inventory',
						namespace: 'my_fields',
						ownerId: 'gid://shopify/ProductVariant/40576138313890',
						type: 'number_integer',
						value: '25',
					},
				],
			},
		})
		console.log(metafields)
		res.status(200).json({ values: metafields })
	} catch (error) {
		console.log(error)
		res.status(500).json(error)
	}


However, the above mutation returns the following error:

Expected value to not be null
Variable $metafields of type [MetafieldsSetInput!]! was provided invalid value

I assume the variable metafields failed to pass into the mutation because when I run the exact same mutation in the Shopify Admin API GraphiQL explorer, there was no error

Screenshot 2021-10-05 at 7.29.30 PM.png

I have also looked into the github repo of @Shopify/shopify-api. In my understanding, variables are added to the query object.

What am I missing?

Thanks,

Howard

--------------------------
Environment: Next js 11.1.2,

Dependencies: ``@shopify/shopify-api`` 1.4.1

Accepted Solutions (2)
Brian_S
Shopify Partner
153 19 39

This is an accepted solution.

Yea - I use Apollo's js client so its a bit different.  I'm not familiar with Shopify's node api but based on a quick scan I'd say you need to set up the `Context` to select which version of the GQL API you want to hit. Check out these docs: 

https://github.com/Shopify/shopify-node-api/blob/main/docs/getting_started.md#set-up-context

 

Also - take a look at their test files and how they're sending variables with the query.  I don' t know if you're formatting it incorrectly or just differently, but there does seem to be another way: 

https://github.com/Shopify/shopify-node-api/blob/main/src/clients/graphql/test/graphql_client.test.t...

 

const queryWithVariables = {
      query: `query FirstTwo($first: Int) {
        products(first: $first) {
          edges {
            node {
              id
          }
        }
      }
    }`,
      variables: `{
        'first': 2,
      }`,
    };

 

 

 

client.query({data: queryWithVariables})

 

Brian Singer
CTO & Cofounder of Subscription Service - Awtomic

View solution in original post

yiuhoward
Tourist
3 1 2

This is an accepted solution.

Thank you so much for your reply again Brian! I really appreciate your help.

 

You are right about the syntax.  The following code works now:

const metafields = await client.query({
			data: {
				query: `mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {
					metafieldsSet(metafields: $metafields) {
						userErrors {
							field
							message
						}
						metafields {
							key
							value
						}
					}
				}`,
				variables: {
					metafields: [
						{
							key: 'cb_inventory',
							namespace: 'my_fields',
							ownerId: 'gid://shopify/ProductVariant/40576138313890',
							type: 'number_integer',
							value: '25',
						},
					],
				},
			},
		})

 

You are also right about setting the context.  By initiating the context, I'm able to set to use the intended API version.

Shopify.Context.initialize({
	API_KEY,
	API_SECRET_KEY,
	SCOPES: ['read_products', 'write_products'],
	HOST_NAME: HOST,
	API_VERSION: '2021-10',
})

 

 Thank you so much for your help again Brian!

View solution in original post

Replies 4 (4)

Brian_S
Shopify Partner
153 19 39

not 100% sure about this but I've seen issues with the docs as they're written depending on the version of the API you're using but you should try using `INTEGER` instead of `number_integer`

Brian Singer
CTO & Cofounder of Subscription Service - Awtomic
yiuhoward
Tourist
3 1 2

Thank you for your reply Brian!

I've tried again with `INTEGER` but ran into the same error.  My guess is the variable is not passed into mutation as it did not complain about the value of the type property.

 

You mentioned about the version of the API so I also have a look at it of my private app. The response headers indicates that the api version is unstable.

'x-shopify-api-version': [ 'unstable' ]

 

Do you know where can I set the api version of private apps?

I can only find a section where I can set the api version of the webhooks, and it's currently set to 2021-10 (Latest)

 

Brian_S
Shopify Partner
153 19 39

This is an accepted solution.

Yea - I use Apollo's js client so its a bit different.  I'm not familiar with Shopify's node api but based on a quick scan I'd say you need to set up the `Context` to select which version of the GQL API you want to hit. Check out these docs: 

https://github.com/Shopify/shopify-node-api/blob/main/docs/getting_started.md#set-up-context

 

Also - take a look at their test files and how they're sending variables with the query.  I don' t know if you're formatting it incorrectly or just differently, but there does seem to be another way: 

https://github.com/Shopify/shopify-node-api/blob/main/src/clients/graphql/test/graphql_client.test.t...

 

const queryWithVariables = {
      query: `query FirstTwo($first: Int) {
        products(first: $first) {
          edges {
            node {
              id
          }
        }
      }
    }`,
      variables: `{
        'first': 2,
      }`,
    };

 

 

 

client.query({data: queryWithVariables})

 

Brian Singer
CTO & Cofounder of Subscription Service - Awtomic
yiuhoward
Tourist
3 1 2

This is an accepted solution.

Thank you so much for your reply again Brian! I really appreciate your help.

 

You are right about the syntax.  The following code works now:

const metafields = await client.query({
			data: {
				query: `mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {
					metafieldsSet(metafields: $metafields) {
						userErrors {
							field
							message
						}
						metafields {
							key
							value
						}
					}
				}`,
				variables: {
					metafields: [
						{
							key: 'cb_inventory',
							namespace: 'my_fields',
							ownerId: 'gid://shopify/ProductVariant/40576138313890',
							type: 'number_integer',
							value: '25',
						},
					],
				},
			},
		})

 

You are also right about setting the context.  By initiating the context, I'm able to set to use the intended API version.

Shopify.Context.initialize({
	API_KEY,
	API_SECRET_KEY,
	SCOPES: ['read_products', 'write_products'],
	HOST_NAME: HOST,
	API_VERSION: '2021-10',
})

 

 Thank you so much for your help again Brian!