How We Solved Stripe Metadata Issues in Our MERN E-commerce Project


We recently worked on a group e-commerce project using the MERN stack (MongoDB, Express.js, React, and Node.js), and one of the most exciting (and challenging!) parts was integrating Stripe for online payments. 💳
We faced a pretty interesting issue when trying to send metadata (extra information like total amount, user ID, etc.) to Stripe and then retrieving it using a webhook. So I thought I'd share the problem we faced — and how we finally solved it — in case you're also building something similar.
💡 What We Wanted to Do
We were building a full-stack e-commerce app where users could place orders, and we’d store those orders in our database. When a user checks out and pays using Stripe, we wanted to:
Send some custom metadata (like
totalAmount
,userId
,cartItems
, etc.) along with the Stripe session.Use a Stripe webhook to listen for successful payments.
Store the order details in our MongoDB database once the payment is complete.
❌ The Problem We Faced
Everything was working almost fine — until we noticed one big issue:
When we sent metadata with the Stripe session and tried to access it inside our webhook handler, the metadata was either missing or not in the format we expected.
Here’s what went wrong:
Stripe only accepts metadata in key-value string pairs. But we were trying to send an entire object (like a cart or user details) directly.
So when we tried to send
metadata: { cartItems: [ { id: "123", qty: 2 } ] }
, it either failed silently or turned into a string like"[object Object]"
.Inside the webhook, we couldn't read the cart or amount properly, which meant we couldn’t create a full order in our database!
✅ How We Solved It
After lots of debugging and reading Stripe docs (and Stack Overflow posts 😂), we figured out the best way to solve it.
Step 1: Convert Objects to Strings Before Sending
Since Stripe metadata only supports strings, we had to stringify complex data before sending it.
metadata: {
totalAmount: totalAmount.toString(),
userId: userId,
cartItems: JSON.stringify(cartItems),
}
This allowed us to send our cart data safely.
const cartItems = JSON.parse(session.metadata.cartItems);
const totalAmount = parseFloat(session.metadata.totalAmount);
const userId = session.metadata.userId;
Now, everything worked perfectly. We were able to:
Get full cart and user info from the webhook.
Save it as an order in our database,
And send a success message to the user. 🎉
📦 Final Thoughts
Working with Stripe is powerful, but it has some strict rules, especially with metadata. Our biggest lesson? Always stringify complex data before sending it through Stripe metadata, and always parse it back on the server side!
This issue slowed us down for a bit, but it also helped us learn a lot about how Stripe works under the hood.
If you’re working on a similar MERN + Stripe project, I hope this helps you avoid the same pitfall!
Subscribe to my newsletter
Read articles from Mahesh Kunwar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Mahesh Kunwar
Mahesh Kunwar
I am Mahesh Kunwar, a dedicated web developer specializing in the MERN stack—MongoDB, Express.js, React.js, and Node.js. Passionate about creating user-friendly and efficient applications, I enjoy solving complex problems through clean and scalable code. My journey in web development has been shaped by hands-on projects that have enhanced my problem-solving skills and deepened my technical expertise. With a dynamic mindset and a strong enthusiasm for technology, I am always eager to learn new technologies and adapt to emerging trends in the fast-evolving tech landscape. A quick learner, I thrive in collaborative environments, constantly seeking opportunities to contribute, grow, and innovate. My goal is to leverage my skills to develop impactful software solutions that enhance user experiences and drive meaningful progress.