#thewizard2112
1 messages Β· Page 1 of 1 (latest)
Hello! Can you give me the request ID showing that error? Here's how you can find a request ID: https://support.stripe.com/questions/finding-the-id-for-an-api-request
Sure! Here it is: req_yLQjBhC72gtP4y
Looking...
Two things:
- This is a non-public feature, so we can't help with it on this public Discord server. You need to contact Stripe support or the person who gave you access to this private feature for help: https://support.stripe.com/contact/email
- I will say the error message is accurate. You are passing in an empty string for a parameter that does not allow empty strings.
- You mean Subscription Schedule updates is a private feature? Since when? It's been available through the API and SDK for at least 1.5 years and we've never contacted anyone to give us special access π€
- I get that, but there have been no changes on our end so this smells like a breaking change in an existing API, thus a regression
The specific parameter the error is referencing is a private feature.
I can't address #2 here, as this is a public server. You'll need to contact Stripe support or reach out to the person who granted you access to the private feature in question.
Can I ask what private feature you're referring to? As I said, we haven't contacted anyone for any private feature - ever, so I don't really have context on what to even ask :/
Checking...
Ah, okay, turns out this was made public last week, but it looks like some parts of the documentation are still private for some reason.
The parameter on Subscription Schedules isn't public yet, but the same property when updating a Subscription is: https://stripe.com/docs/api/subscriptions/update#update_subscription-invoice_settings-issuer
Okay, so the issue is that you can't set the issuer to an empty string. You either need to specify a connected account ID to use for the Invoice appearance, tax, etc. or you need to omit the property entirely.
The thing is you can't make partial updates (because the API replaces the Schedule), so we just change the fields we need and leave the rest as we got it. This is a field we don't change - we just update with the same value we received.
And again - this code has been this way since August '22, so not sure what's expected of us here TBH
Can you show me a previous request where setting this to an empty string worked?
I think what might be happening, because this is a new feature we recently released, is that your code isn't handling the new property as expected. It's sending it back to us with an empty string as the value instead of omitting the property entirely.
@placid wigeon Does that seem to be what's going on?
That might be it
If so, you should note that we consier adding new properties (and several other things) as backwards-compatible changes, which means your integration is expected to handle them happening at any time: https://stripe.com/docs/upgrades#what-changes-does-stripe-consider-to-be-backwards-compatible
But then I'd expect that value to be correct when I fetch the data from the API - it doesn't make sense to me that there's only one API to update Subscription Schedules, that only allows replacing the entire object, and that the API that retrieves that object gives me incorrect data (and as you said, an empty string is incorrect data), because I have to use that data to do a full replacement. Otherwise I have no way of knowing how to parse the object... Am I supposed to traverse all the properties and remove all the empty strings because it's an invalid value in general? Or is it just in this specific case?
And BTW - this also happens with phases[0][automatic_tax][liability]
And we only started getting empty strings from the API today
So I assume the update API is not the problem, but that the GET API returns bad values
I'm not sure I fully understand. The property on the object being unset is valid. You attempting to set it to an empty string is not valid.
Can you share the raw body of one of the GET responses you're referring to? Is the JSON showing these values as empty strings, null, or something else?
We pass these values on as-is from the GET API (subscriptionSchedules.retrieve) and that has empty strings
No manipulation whatsoever
Right, but that's not a valid approach.
Some values coming from the API are read-only. Some have values that can't be set by you to the current values.
Well I wish I could use the amend API but that's still in beta... So this is the only reasonable way of doing it without traversing the entire object and reconstructing it with intimate knowledge of each field (even though we only care about a couple)
Also - you said these fields are not read-only, and that empty strings for these are not valid, so why are we getting invalid values anyway?
BTW the SDK is not giving type errors for this stuff (which makes sense because we didn't update it), and those new fields are also not part of the type definition. I know Typescript is not sound, but still this change is breaking in a very unexpected way, especially since we didn't change the API version
Hi, stepping in and catching up.
Thanks @restive quest and thanks @deep garnet for your incredible patience!
I need to test this on my end and may take some time. Thank you for your patience.
I had another teammate take a look here as well. After testing, it looks like our Node SDK treats "" as null and that it where this issue is coming from.
You can't take phases from your retrieval and pass those through to the update them
So what's the recommended approach here?
Because honestly if I can't do a partial update in any way, it's kinda useless :/
What you're trying to do is not possible
We've been doing it for a year and a half now... So is it no longer possible because additional breaking changes will be introduced and there's no way to determine if they're breaking, or specifically because of those 2 fields? Because if it's just these ones we can explicitly omit them from the update
No, itβs only worked for you thus far because you've been lucky with which attributes are set/not set.
Can you plz explain what changes broke this?
And is the official statement "You can only update Subscription Schedules by replacing them and there's no good way of getting the current (correct) Schedule"?
No changes broke this. You can't unset this property.
We don't want to unset it, we don't care about this property. We just want to make explicit changes to other fields. There's no way to do this other than replace the entire object, so we have to leave this field as it is, but to know what it is we have to take it from somewhere - and that's the GET API
As a concrete example - we want to change the price on a phase in an existing Schedule.
Or another one - we want to add a phase
I had to read the chat again and I'm not fully understanding what you're doing here. You can't pass these values as-is from the retrieve call.
That's what I'm doing :/
You can only update the following when you make the SubscriptionUpdate Schedules: https://stripe.com/docs/api/subscription_schedules/update#update_subscription_schedule-phases-items.
Sorry, maybe I wasn't clear - this is specifically about phases (the errors I sent were about fields inside of phases so I assumed we're on the same page)
So when I update a phase I take the existing as-is and just change the price
I'll send a simplified example in a sec
So here we're getting the Schedule phases and mapping them to update params (the types are incompatible as you've mentioned)
And the createSubscriptionSchedulePhaseUpdateFromExisting function simply maps the keys to compatible update params based on the Stripe.SubscriptionSchedule.Phase type.
So if I understand correctly, the original assumption that the types are stable as long as we don't change the API version is wrong, because new properties can be added at any time?
π stepping in as pgskc needed to step away
Catching up
So to start with, there is generally a lag of a week or two before types get added to our SDKs for new features. But really, the way you have built this code is not a safe way to proceed. As noted, you have indeed been fortunate that it has not broken up until now, but really the adding of optional parameters is not considered to be a breaking change for our API and thus you should be only passing in the parameters that you specifically want to use for your update. This does mean you should be building the phases themselves, and yes you can use the Sub Schedule retrieval to help you do that by grabbing specific properties that you are going to use, but no you should not solely rely on that and just spit back out whatever that Schedule responds with.
Ok thanks for the clarity. So given I only want to change 1-2 fields in a phase and leave the rest as-is, is there any way I can ascertain whether a nested empty string in some field inside of a phase is valid or should be omitted? Or do we just play whack-a-mole and hope we get a long streak of luck again? π
You don't play whackamole at all
You write your code to specifically only update the parameters you care about
So just because there is a new property returned when you retrieve the Sub Schedule, that doesn't change your code at all in terms of what you pass to the Sub Schedule update API
Yes - but I'm talking about phases specifically, from our testing you can't pick specific fields in a phase to update, you have to replace the entire thing
I'm not sure what you mean by that
Like yes you can't just pass the parameters that you want to update
You do have to pass all the relevant parameters for setting the phase correctly.
And for previous phases this will oftentimes mean passing in the same data again.
But that's just how the API works
It still means you need to ensure you only pass in those parameters for the phase you care about
Not just everything that is retrieved for that phase
Yes, that's what we do when creating a new phase, but we also change existing phases
And that created some issues when we didn't pass all the fields as they are already set
Right I understand
To say it bluntly: you (likely unintentionally) took a shortcut and now it has come back to bite you
You will need to change your code to not just re-pass that Phase directly as it was returned from retrieving the Sub Schedule
You will need to retrieve the Sub Schedule and then pick out each of the necessary pieces and pass that to your update request
I do understand this is a hassle
But it is just how this API works
Just to make sure I understand - you're saying we need to get the phases as they are currently defined, and create new phases while only setting the fields I 'care' about?
Correct. By "care" I just mean that instead of passing in things as an empty string or null or something (since that is what the retrieval of the Sub Schedule gave you) you would need to omit those parameters.
I understand. I think the original thought behind doing it this way is this: we don't necessarily know what we should care about. What if a schedule was created in the UI and it changes the payment method? Then we might accidentally remove that update when we change the price, right? If we don't pass it along that is
Hmmm I don't really follow.
You still retrieve the Schedule
So you would still know that "phase 3 updates the PM"
And thus you do "care" about that parameter.
But in your code you have established that if a PM update is present then you should include that.
Versus with invoice_settings.issuer
Nothing in your flow involves that
So you should never be passing that yourself
Basically you do need to code defensively here
Right, but even if we only take fields we care about this can happen. Like, if we have an object that is somewhat complex, we can't just take it as-is (automatic_tax for instance) - we have to do something like automatic_tax: {enabled: phase.automatic_tax.enabled}
That's the only way we can guarantee we're not getting additional fields
So I guess we have to blow up all the nested objects and pick the props the SDK knows
I don't really understand your example. You know that you are working with Auto Tax in your flow, thus you do want to check on that and then you can pass that each time?
Yeah, for instance
So I pass that to the update API as I received it, but there's a new field that breaks the update
You ignore the new field
Because it was never a part of your integration before
So you don't even know there was a new field to begin with
Yeah ok I understand
Honestly that's very inconvenient π
But I thank you all nonetheless π You all have been extremely helpful
BTW - any idea when the amend API is out of beta?
Might be useful here
Happy to help and sorry about the inconvenience -- I know it isn't the easiest API to work with (thus the amendments beta, etc.). Unfortunately we really only support GA products so we don't focus too much on those betas before they become GA. I'm not sure the timeline for amendments but I hope soon
Alright, thx again! I know this was an ordeal for you guys, sorry
No problem