Updating object properties in an array on a document with the Sanity client
Unfortunately, dec() (and inc()) operations don't support JSONMatch path syntax with array selectors like variants[_key == "..."].quantity. These operations only work with simple dot-notation paths like stock or nested.field. That's why you're getting a 400 error.
The patches documentation shows that inc and dec work with simple paths, while the JSONMatch syntax (like arrayField[_key == "value"].property) is supported by set, unset, and setIfMissing operations.
Here's the solution using set with the JSONMatch path syntax:
const promises = data.overview.cartContents.map(async (item) => {
// First, fetch the current quantity
const doc = await client.fetch(
`*[_id == $id][0]{"currentQty": variants[_key == $variantKey][0].quantity}`,
{ id: item._id, variantKey: item.variant }
);
// Then set the new decremented value
return await client
.patch(item._id)
.set({
[`variants[_key == "${item.variant}"].quantity`]: doc.currentQty - item.quantity
})
.commit();
});The key changes:
- Use
set()instead ofdec(): The JSONMatch path syntax works withset, not withinc/dec - Computed property names: The square brackets
[]around the template literal are required to create a dynamic property name - Fetch first, then calculate: Since you can't use
dec()directly, fetch the current value, calculate the new value, andsetit
Here's a cleaner syntax example from the array patching documentation:
await client
.patch('document-id')
.set({
'variants[_key == "abc123"].quantity': 42
})
.commit();Alternative: Use a transaction for atomic updates
If you're concerned about race conditions between the fetch and set operations, you could use Sanity Functions or handle the calculation server-side where you have better control over concurrency.
The limitation exists because inc and dec are designed as atomic operations that work on simple paths, while JSONMatch expressions with array filtering require more complex evaluation that isn't supported with these numeric operations.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.