Shopify Flow: Mastering Metafields & Admin API in 'For Each' Loops
Hey there, fellow store owners and automation enthusiasts!
If you've ever dipped your toes into the powerful waters of Shopify Flow, you know it's an incredible tool for automating those repetitive tasks that eat into your precious time. But sometimes, even the most straightforward-looking automation can throw a curveball. Recently, a fascinating discussion popped up in the Shopify Community forums that perfectly illustrates one of these head-scratchers: dealing with "invalid variable" errors when trying to update metafields via the Admin API inside a "For each" loop.
Our community member, mn175787, was building a super useful flow: a scheduled daily check to see if product variant costs (synced from Printful) had changed. If they had, the flow would send an internal email alert and then update a last_known_cost metafield on the variant. A brilliant idea for keeping tabs on profitability!
The snag? An error message that read: "getProductVariantData_item is invalid. Replace this variable." This popped up in the "Send Admin API request" action, specifically within the metafieldsSet mutation, even though the action was correctly placed inside the "For each" loop. Sound familiar?
Untangling the "Invalid Variable" Mystery in Shopify Flow
When you're working with Shopify Flow and hitting the Admin API, especially within loops, there are a few common pitfalls that can lead to these frustrating "invalid variable" errors. Luckily, the community came through with some stellar insights. Let's break down what our resident experts, tim_tairli, lumine, and Maximus3, uncovered.
1. The Crucial "Foreachitem" Variable Rule
This was one of the biggest "aha!" moments from the thread, highlighted by both tim_tairli and Maximus3. When you're using a "For each" loop to iterate over a list of items (like product variants in this case), the variables you reference within that loop need a special prefix: Foreachitem.
Think of it this way: when you're outside the loop, getProductVariantData might refer to the entire collection of data. But inside the loop, for each individual item, Flow needs to know you're talking about that specific item in the current iteration. So, instead of trying to use something like {{getProductVariantData_item.id}}, you should be using {{getProductVariantDataForeachitem.id}}.
Pro Tip: Always use the "Add variable" button in Shopify Flow's action configuration. It's smart enough to usually pick the correct variable name, including that all-important Foreachitem prefix when you're within a loop context.
Here's a visual example shared by tim_tairli that shows this in action:
2. Demystifying Metafield Data Types and the GID
This is where things can get a little tricky with GraphQL and metafields, as lumine eloquently explained. Even if you want to store a number, the value field in a GraphQL metafieldsSet mutation must be passed as a String. The type argument (like number_decimal) then tells Shopify how to interpret that string. So, while it might look like you're putting a string where a number should be, it's actually the correct GraphQL syntax!
The other big one is the ownerId. When setting metafields, you need to provide the full GraphQL ID (GID) of the resource you're attaching the metafield to. This isn't just the plain numeric ID you might be used to. It looks something like gid://shopify/ProductVariant/123456789.
If your variable (even the correct Foreachitem one) only resolves to the numeric ID, you'll need to manually construct the GID string.
Here’s how to ensure your mutation inputs are correctly formatted:
- For the
ownerId: Make sure you're providing the full GID. If{{getProductVariantDataForeachitem.id}}only gives you the numeric ID, you'd construct it like this:"ownerId": "gid://shopify/ProductVariant/{{getProductVariantDataForeachitem.id}}" - For the
value: Your variable should be enclosed in quotes, even if it's a number. Shopify Flow generally handles the conversion, but if the variable resolves to null or an invalid format, it will throw an error."value": "{{getProductVariantDataForeachitem.inventoryItem.unitCost.amount}}", "type": "number_decimal"
The user's original setup for the value field was actually correct in terms of GraphQL syntax (string in quotes). The underlying issue was more about the variable resolution itself or potential null values, which brings us to our next point.
3. Guarding Against Null Values
Sometimes, the data you're pulling might not always exist. Lumine wisely pointed out that if a variant from Printful (or any other source) sometimes returns a null cost, and that null flows into your variables block, it will also be rejected as invalid. This is a common silent killer for flows!
Actionable Step: Consider adding an extra condition in your flow *before* the "Send Admin API request" action. This condition would check if the inventoryItem.unitCost.amount actually has a value. If it's null, you could either skip the metafield update for that variant or send a different alert.
Putting It All Together: Your Revised Flow Snippet
Based on the collective wisdom of the community, here’s what your Mutation inputs for the "Send Admin API request" action should look more like, assuming getProductVariantData is the name of your "Get product variant data" action:
{
"metafields": [
{
"ownerId": "gid://shopify/ProductVariant/{{getProductVariantDataForeachitem.id}}",
"namespace": "custom",
"key": "last_known_cost",
"value": "{{getProductVariantDataForeachitem.inventoryItem.unitCost.amount}}",
"type": "number_decimal"
}
]
}
Remember, the screenshots mn175787 shared (like this one
) showed the action correctly placed within the loop, which was a good start! The main fix truly boils down to those variable names and ensuring the GID format.It’s these little nuances in Shopify Flow, especially when you're diving into the Admin API, that can make all the difference. The community's collaborative spirit in dissecting these issues is truly invaluable. So next time you're scratching your head over an "invalid variable," remember these tips, give that "Add variable" button a good workout, and don't hesitate to check the GID format and for any sneaky null values!
Happy automating!

