#rocket_error
1 messages · Page 1 of 1 (latest)
Below are links to other discussions we've had with you in the past week in case you want to review that information. If your question is related to one of these previous discussions, please provide a comprehensive summary of the current state and what you need help with now. We help many users simultaneously, so a summary allows us to resolve your issue as soon as possible.
- rocket_error, 20 hours ago, 65 messages
👋 Welcome to your new thread!
⏲️ We'll be here soon! We typically respond in a few minutes, but in some cases we might need a bit more time (e.g., server's busy, you've got a complex question, etc.).
⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can start a new thread if you have another question.
🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1248428058524778558
📝 Have more to share? Add details, code, screenshots, videos, etc. below.
might be helpful for more context, my thread from yesterday: #dev-help message
error in question: https://dashboard.stripe.com/logs/req_duISuNNGxdQLLq
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
error logs in vercel
Could you summarize the last state of yesterday thread? Were you able to find the information you want in your webhook function?
so I was able to resolve what I thought was the root cause of the issue
essentially it seems like there was an error with JSON.parse
so I resolved that
however it appears there's some other cause of this error
with the error being multiple attempts to capture a paymentintent
another instance of the error just happened
all I know is that the webhook endpoint is getting a 500
request ID is req_CJj0k970tijcZl
same issue with "This PaymentIntent could not be captured because it has already been captured."
Yeah you can see it in your Dashboard log https://dashboard.stripe.com/test/logs
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
It was originally captured by req_CY54wZFwsCF6nx
yeah i'm unsure what's causing the initial failure
You mean the initial capture?
I guess?
as in
why the initial capture failed which then led to these recapture requests
it only says 504 gateway timeout on my vercel logs
where can I search with this? I tried putting this in resource ID but it doesn't work
It's succeeded in Stripe log so could be just the connection issue
Can you reproduce it constantly?
no not constantly
it only happened once
there was one other instance of an error
but i think that may have been from something else
I think the other instance was just due to a failed recapture last night that tried again
here is my endpoint code, wondering if anything catches your eye for a potential cause
so the error occurred one other time which was earlier today at 2pm EST
just a generic 500 error on vercel's end, nothing more that I can use to figure out
req_4CADZQ4Q9XPbQn is the id
Same that it was captured before on req_lojGtfXjrzr7J8
You would want to look at what happened on req_lojGtfXjrzr7J8. None of it and req_4CADZQ4Q9XPbQn was at 2pm EST
could you elaborate on this not sure I understood what you said
So req_lojGtfXjrzr7J8 was the first time you captured the PI and it was succeeded
Then you retried multiple time, including req_4CADZQ4Q9XPbQn and it failed because the PI is already captured
Looks like you are recapturing the same PI, which leads to the error
I don't understand how that could happen though
I only have one request to capture the payment intent
const paymentIntent = await stripe.paymentIntents.capture(payment_intent_id);
if (paymentIntent.status !== "succeeded") {
return NextResponse.json({
error: `Payment failed`,
});
} else {
//Send email with codes
await resend.emails.send({
...
});
return NextResponse.json({ success: true });
}```
this is the very end of my endpoint
what could cause it to recapture again?
ah so it seems like the task is timing out?
Task timed out after 15.02 seconds
strange that is later on
so that's not necessarily the issue
so I'm looking at
req_CY54wZFwsCF6nx
this is the initial capture for the error from today
Does this code run repeatly with a same PaymentIntent Id?
when looking in the vercel logs, there appear to be two requests to the stripe endpoint for some reason
I don't think so?
my endpoint code is here https://codeshare.io/8Xq0oJ
I see the code, but you would want to add log to log the time, and the payment intent id before the capturing logic
ie if we look at pi_3POSohHvAVLYAKEc1UmwGdcc
- The first succeded request is req_lojGtfXjrzr7J8 on 2024-06-05 23:00:34
- Next failed request is req_DxaRDk4xdXumcp on 2024-06-05 23:00:53
- Next is req_FaoKzoWxllF7ET on 2024-06-06 00:01:59
- Next is req_R1e0lgH1CE0XhU on 2024-06-06 03:59:48
- Next is req_4CADZQ4Q9XPbQn on 2024-06-06 18:09:54
Time is UTC
The times are quite different. Looks like your code could have been trying to capture in different places
You can copy and paste all the request id above to your Dashboard search and see the history
well aren't these repeats because stripe automatically retries
when a request fails it retries with increasing intervals which is what it appears to be
retries to which webhook event?
wait
if you don't mind
can we examine req_CY54wZFwsCF6nx
I can't see the vercel logs for the request you mentioned
so I'm cross referencing stripe and vercel logs for req_CY54wZFwsCF6nx
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
I can see the successful request is 7:27:09
when I go on vercel logs
I see two requests for some reason
one at 7:27:07 which is successful
and then another at 7:27:08 which throws a 504
gateway timeout
Ok first, when you received checkout.session.completed, did you response 200 to Stripe?
If you don't we will keep retrying to send it to you
and you will end up with calling the same logic multiple times
I believe so because the first one has a 200 status right?
and also most payments appear to work
I am looking at pi_3POSohHvAVLYAKEc1UmwGdcc, and its checkout.session.completed is evt_1POSomHvAVLYAKEcck1qBpUt which hasn't received a 200 response
The recommended practice is always respond 200 to Stripe first, before doing your logic. Because we have some timeout to mark the deliver as failed
so I should respond 200 at the top?
not sure how I could respond 200 before I finish my logic
Good question. The ideal way is to pushing the event to some internal queue, and process the queue later, then return 200. When you process the queue, you can call capture API
But before going that far, could you make sure to just respond 200 in the end of your function?
Like, no matter which route it goes, respond 200 in the end
ok added that
i don't understand why this is happening for this request and not every other request
a large majority of them all work
is there a possibility that a paymentIntent will be captured successfully but not give a status of succeeded?
const paymentIntent = await stripe.paymentIntents.capture(payment_intent_id);
if (paymentIntent.status !== "succeeded") {
return NextResponse.json(
{
error: `Payment failed`,
},
{ status: 200 }
);
} else {
//Send email with codes
await resend.emails.send({
...
});
return NextResponse.json({ success: true }, { status: 200 });
}```
the issue i'm encountering is that the email isn't being sent even though it seems the payment intent was indeed captured
which makes me think that somehow, the paymentIntent was captured but it didn't return a status of "succeeded"
So you only respond back to Stripe if the call to capture PaymentIntent succeeded. Tha’s true for most case, but if you sent out the request then connection lost, your code timeout but Stripe still receive the request and process to capture
You may want to move the email sending to when you received payment_internt.captured instead
that guaranteed the PI is captured and isn’t related to the API call earlier on checkout.session.completed
so listen for a different webhook event?
it seems payment_intent.captured doesn't exist
do you mean payment_intent.succeeded?
oh sorry, 1 min
I thi k it’s payment_intent.amount_capturable_updated
could you start a stripe listen in Stripe CLI and listen to all event
then send a capture API in Test mode
to inspect which event it sends?
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
the CLI hasn't been working for me
Why? It’s an useful tool to test webhook
i'm having issues setting up: I added the path of stripe.exe to my path environment variables but stripe isn't recognized as a command
but besides that, why would you say it's amount capturable vs succeeded
I think their timing could be different. I can test for you in 30mins ish but I really recommend to setup Stripe CLI and test in Test mode
I've tried, I just can't get the command to work
greatly appreciate your time by the way
I know it's very valuable and I can't thank you enough for your time
I just ran
the stripe cli
2024-06-06 22:13:37 --> payment_intent.amount_capturable_updated [evt_3POsJ8HvAVLYAKEc0e3NpbjA]
2024-06-06 22:13:37 --> payment_intent.created [evt_3POsJ8HvAVLYAKEc0QvGsmaY]
2024-06-06 22:13:37 --> charge.succeeded [evt_3POsJ8HvAVLYAKEc0IapNmeE]
2024-06-06 22:13:38 --> checkout.session.completed [evt_1POsJAHvAVLYAKEcoCXHvZWJ]```
here is what I got
the flow
by the way, my endpoint code already listens for the checkout.session.completed event
everything works as intended
no errors
I setup the flags to forward it to my localhost
so that it can trigger my endpoint
Yeah okie then let's capture the PI, which webhook event you get?
uhh what do you mean
I get these events
but for my endpoint, I listen for the checkout session completed event
Okie I see, no worry
So before capture you will get payment_intent.amount_capturable_updated
after capture you will get payment_intent.succeeded
So you can move the email sending logic over when received payment_intent.succeeded
oh I don't think I got payment_intent.succeeded
And keep the calling Capture API logic on checkout.session.completed
when I listened for all events I don't think I got an event for payment_intent.succeeded
oh wait let me try again
because I didn't capture
Yeah
hm
for the flow, I don't know if I can separate it to a different endpoint
since I'm checking for something in the database and then removing it
I don't want to capture the payment intent first because what if the item in the database doesn't have enough quantity?
You can keep your flow of logic until calling Capture PaymentIntent API, in checkout.session.completed, no?
Only the logic of sending email, move it over to payment_intent.succeeded
but I need variables declared in the code
products
for example
I fetch from the database and then send at the end in the email
unless there's a way to forward that data to the payment_intent.succeeded endpoint but I don't think so
also I still don't know why it's failing in the first place
i've only started encountering this recently
is the payment intent capture succeeding but somehow not returning the response in time?
Let's put the "why it happen" part aside. It is the connection and it could happen sometimes, depends on the network between your node and Stripe server
You can fetch the products from the database again, when you receive payment_intent.succeeded, no? It's a different thing
yes but doesn't that seem extremely redundant
because i'm doing all the fetching and whatnot already in the checkout.session.completed
and then I would need to fetch from the database again
is there a way for me to retrieve the lineItems for the payment_intent.succeded event?
Yeah you can call Retrieve PaymentIntent and expand what it's not already for you in the event body
could you please provide an example
so I retrieve the paymentId from the event
and then make a call to retrieve that paymentIntent using the id
and then expand?
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
the payment intent object doesn't seem to have a line_items property, would that still work?
On the request to retrieve, expand the line_items.xxx depends on what you want to retrieve
hm okay let me try that
it doesn't seem like I can expand line_items on the paymentIntent
const paymentIntentId = event.data.object.id;
const paymentIntent = await stripe.paymentIntents.retrieve(paymentIntentId, {
expand: ["line_items"],
});
console.log(paymentIntent);```
hello! stepping in on behalf of orakaro, you need to expand line_items from the Checkout Session : https://docs.stripe.com/api/checkout/sessions/object#checkout_session_object-line_items
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
how can I access that from the payment_intent.succeeded event though
also thank you to orakaro for the hours of assistance 🙏
why do you want to access it from the payment_intent.succeeded event? you should listen for the checkout.session.completed event
you can listen to more than 1 event
uh
yes but I'm listening to it from a different route
so what is happening is it appears that my webhook endpoint is sending a request to capture
but for some reason, my code to send an email isn't executing
here is what it looked like
my endpoint code is here https://codeshare.io/8Xq0oJ
this has worked perfectly fine until the past two days
when I started getting 500 errors for some odd reason
these are the vercel logs for an instance of the error i'm talking about
and this is connected to req_CY54wZFwsCF6nx
so it is successfully captured, but for some reason, the endpoint gets called again
have you tried walking through your code step by step? to see why the endpoint gets called again?
I have, I don't understand why it would
const paymentIntent = await stripe.paymentIntents.capture(payment_intent_id);
if (paymentIntent.status !== "succeeded") {
return NextResponse.json(
{
error: `Payment failed`,
},
{ status: 200 }
);
} else {
//Send email with codes
await resend.emails.send({
...
});
return NextResponse.json({ success: true }, { status: 200 });
}```
this is the very end of my endpoint codew
which also leads me to ask, why wasn't my email code executed. was it something with the paymentIntent capture?
because if there was an initial capture request for the payment intent that succeeded, then my code to send the email should have executed
but it hasn't
also for context, i've had close to 20 payments today, but this error has only occurred once
so it's not something that I was able to reproduce consistently either, i'm not sure why it's happening
it was also working fine before for the past few months until 2 days ago
to clarify, the problem with 500 error code responses is solved already?
what do you mean? Are you or are you not receiving a 500?
as in
I have received a 500
but only for a singular payment
and I'm unsure why
I cannot reproduce more 500s
so lets take this one step at a time
what's the request id where you received 500 in response for?
I just received one right now actually
I'll send that one
here is the event ID
evt_1POpi3HvAVLYAKEcIa8sjLDd
and then here is the error request ID: req_hM81fSHL5EyBTQ
this is all I see in my vercel error logs
^ above includes the initial successful capture request
so there's an initial request to capture the paymentIntent that succeeds
but i'm not sure why another one is being sent
again, lets solve the problem one step at a time and focus on the 504 first
okay what is your proposed first step I should do?
From Stripe's end, we receive a 504. The headers seem to indicate that you're also using Cloudflare. So it seems like somewhere in your server along the way, a 500 / 504 is being returned. The first step you need to do is to trace where exactly the 500 is being sent/returned from. It's not possible for us to help you track / trace that down. You may need to trace through your network logs to identify if it's being returned by your app / vercel / or possibly further downstream. Then if it's from your app, you need to identify the exact line of code that is causing this
Since 504 (Gateway Timeout) status code indicates that the server, while acting as a gateway or proxy, did not receive a timely response from an upstream server - like what Orakaro said, you should return 200 first before performing any complex logic. I don't see the changes reflected in codeshare though
the codeshare expired, I'll send an updated one with the current code
ah never mind, I've updated it
so yes, those changes weren't yet present in the 504
I have also turned off cloudflare proxying
if you received another 500 after you've made those changes, my steps still apply
yes these are after I had made the changes
this was a pure 500, not 504
it may be a 500 in your logs, what Stripe sees is a 504
for this most recent error?
then perhaps it is cloudflare
say I wanted to go the route of returning 200 first
how could I return a response but then execute after?
ah sorry, i was looking at an older attempt. Yes, the latest attempt is 500
mm so the 504 is likely because of cloudflare
if this helps, I had added console logs before each instance of returning a response
and there was a payment 3 minutes before the 500 error I mentioned above
and it seems there is a difference
you need to implement your own logic to store the requests from Stripe, then execute them in order
so this payment the checkout 200'd and also displayed the console log message I had written
however the one that errors out doesn't display any console log message
would you have any ideas as to whether or not this might be relevant
nobody will know why your app is returning a 500. You need to add additional logging, walk through your code to identify the exact line that is causing issues
does anything in the codeshare catch your eye? I've added logs before each response, which also returns a 200 no matter what happens
why are you returning 200 if the request doesn't have a signature?
orakaro said this
should I change that to a 403?
no, you shouldn't change it to a 403. Orakaro said to always respond with 200 upon receipt of the request. How does returning 200 if the request doesn't have a signature match with what Orakaro said?
so if the request has a signature, it's not going to respond with 200 at that point right?
no?
because returning a response would end the execution of the rest of the code
so if it has a signature it would just proceed with the rest of the code?
am I understanding it wrong
if you look at every instance where I return a response, there is a status 200
You need to rework your entire server side logic to be able to store the request for later processing, and respond to the request with 200. This isn't something that can be achieved with a single line of code
putting aside returning 200 first. You need to track down where exactly in your code there is an error which results in 500 being returned
again, i don't know. You need to track / debug your own code for this
I see
other than the 200 issue
do you see anything else that raises suspicion?
would the api version be a potential cause?
no, the api version is not a cause
also, is there anyway to prevent stripe from retrying the event?
it seems like the error I got was actually connected to the 504 from a while back
Stripe retries an event when we don't receive a 2XX response
hmm
would adding a line towards the beginning to check if a payment intent status is "succeeded" help resolve that?
you can try
will do
okayt
so after adding that check at the beginning
I was able to resolve that recurring 500
so far with the revised code I haven't encountered a 500 yet
I guess I will wait and see if the issue arises again
perhaps cloudflare proxy was the root cause
thank you for your assistance orakaro and alex, it's greatly appreciated