Handling Stripe webhook errors with Netlify Serverless Functions and SANITY
The issue you're experiencing is likely due to the forEach loop not waiting for the Sanity patch operations to complete before the serverless function returns. Your function is returning a 200 response immediately while the Sanity updates are still in progress, which can cause connection issues and timeouts.
Here are the key problems and solutions:
Main Issue: Fire-and-forget pattern
Your current code uses forEach with non-awaited promises. The function returns before the Sanity patches complete, causing the connection to close prematurely.
Solution: Use Promise.all with map
Replace your forEach loop with this:
// Wait for all patches to complete before returning
await Promise.all(
lineItems.map(async (item) => {
const sanityId = item.price.product.metadata.sanityId
try {
await client
.patch(sanityId)
.dec({ stock: item.quantity })
.commit()
} catch (err) {
console.error(`Failed to update ${sanityId}: ${err.message}`)
// Consider whether you want to throw here or just log
}
})
)Additional recommendations:
- Move client initialization inside the handler - Creating the client outside the handler can cause connection pooling issues in serverless environments:
const handler: Handler = async ({ body, headers }) => {
const client = sanityClient({
projectId: process.env.GATSBY_SANITY_ID,
dataset: process.env.GATSBY_SANITY_DATASET,
token: process.env.SANITY_TOKEN,
useCdn: false,
apiVersion: "2022-02-01",
})
// ... rest of your code
}Update your API version - You're using
2022-02-01, which is quite old. Consider using a more recent version like2024-01-01or later.Consider using Sanity Functions instead - Since you're already using serverless functions, you might want to explore Sanity Functions which are native to the platform and handle these connection issues more reliably. They're designed specifically for this type of webhook processing and provide better integration with Sanity's infrastructure.
The TLS connection error you're seeing is a symptom of the network connection being terminated while the client is still trying to communicate with Sanity's API. Making sure all operations complete with await before returning will resolve this.
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.