#thewizard2112

1 messages Β· Page 1 of 1 (latest)

ember scrollBOT
deep garnet
placid wigeon
#

Sure! Here it is: req_yLQjBhC72gtP4y

deep garnet
#

Looking...

#

Two things:

#
  1. 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
#
  1. I will say the error message is accurate. You are passing in an empty string for a parameter that does not allow empty strings.
placid wigeon
#
  1. 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 πŸ€”
  2. 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
deep garnet
#

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.

placid wigeon
#

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 :/

deep garnet
#

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.

#

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.

placid wigeon
#

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

deep garnet
#

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?

placid wigeon
#

That might be it

deep garnet
placid wigeon
#

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

deep garnet
#

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?

placid wigeon
#

We pass these values on as-is from the GET API (subscriptionSchedules.retrieve) and that has empty strings

#

No manipulation whatsoever

deep garnet
#

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.

ember scrollBOT
placid wigeon
#

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

restive quest
#

Hi, stepping in and catching up.

placid wigeon
#

Thanks @restive quest and thanks @deep garnet for your incredible patience!

restive quest
#

I need to test this on my end and may take some time. Thank you for your patience.

restive quest
#

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

placid wigeon
#

So what's the recommended approach here?

#

Because honestly if I can't do a partial update in any way, it's kinda useless :/

restive quest
#

What you're trying to do is not possible

placid wigeon
#

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

restive quest
#

No, it’s only worked for you thus far because you've been lucky with which attributes are set/not set.

ember scrollBOT
placid wigeon
#

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"?

restive quest
#

No changes broke this. You can't unset this property.

placid wigeon
#

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

placid wigeon
#

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

restive quest
#

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.

placid wigeon
#

That's what I'm doing :/

restive quest
placid wigeon
#

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?

late umbra
#

πŸ‘‹ 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.

placid wigeon
#

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? πŸ˜…

late umbra
#

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

placid wigeon
#

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

late umbra
#

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

placid wigeon
#

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

late umbra
#

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

placid wigeon
#

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?

late umbra
#

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.

placid wigeon
#

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

late umbra
#

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

placid wigeon
#

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

late umbra
#

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?

placid wigeon
#

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

late umbra
#

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

placid wigeon
#

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

late umbra
#

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

placid wigeon
#

Alright, thx again! I know this was an ordeal for you guys, sorry

late umbra
#

No problem