clerk / clerk/clerk-sdk-ruby

Date::Error ("invalid date") deserializing organizations.get_billing_subscription — API returns proration_date: "" but the Date decoder only handles nil

Open Beginner friendly
#138 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Ruby
Stars
32
Forks
19
Avg merge
19h 27m
Merged PRs (30d)
1

Description

Summary

sdk.organizations.get_billing_subscription raises Date::Error: invalid date while deserializing a successful (HTTP 200) response, because the live API returns "proration_date": "" on subscription items and the generated date decoder only tolerates nil, not an empty string.

Environment

  • clerk-sdk-ruby 7.0.0
  • Ruby 3.3.1

Reproduction

Call the endpoint for any organization whose billing subscription contains an item with no proration (in our case: an org with an active paid plan plus the upcoming default free plan item):

require "clerk"

Clerk.configure { |c| c.secret_key = ENV["CLERK_SECRET_KEY"] }
Clerk::SDK.new.organizations.get_billing_subscription(organization_id: "org_...")
# => Date::Error: invalid date

The API responds 200 with a payload shaped like:

{
  "object": "commerce_subscription",
  "status": "active",
  "subscription_items": [
    {
      "object": "commerce_subscription_item",
      "status": "active",
      "proration_date": "",
      "period_start": 1783554837166,
      "...": "..."
    }
  ]
}

Root cause

CommerceSubscriptionItem declares the field as an optional ISO date:

# lib/clerk/models/components/commercesubscriptionitem.rb:46
field :proration_date, Crystalline::Nilable.new(::Date),
      { 'format_json': { ..., 'decoder': ::Clerk::Utils.date_from_iso_format(true) } }

but the decoder only short-circuits on nil:

# lib/clerk/utils/utils.rb
def self.date_from_iso_format(optional)
  Kernel.lambda do |s|
    return nil if optional && s.nil?
    return Date.iso8601(s)   # Date.iso8601("") raises Date::Error: invalid date
  end
end

So any generated model with an optional ::Date field breaks the moment the API emits "" instead of null — which the billing subscription endpoint does for proration_date today. Isolated:

Clerk::Utils.date_from_iso_format(true).call("")
# => Date::Error: invalid date

Suggested fix

Either (or both):

  • Treat blank strings as absent in the optional decoder: return nil if optional && (s.nil? || s.empty?) — presumably a fix in the Speakeasy generation config since this file is generated; or
  • have the API emit null rather than "" for absent date fields, matching the OpenAPI schema the SDK is generated from.

As-is, the typed client cannot read this endpoint's real responses at all; we've had to fall back to fetching and parsing the raw JSON.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with lib/clerk/utils/utils.rb and the generated model at lib/clerk/models/components/commercesubscriptionitem.rb; run Clerk::Utils.date_from_iso_format(true).call("") to reproduce the failure. Check the Speakeasy generation configuration or API behavior identified in the issue, then verify organizations.get_billing_subscription can deserialize a subscription item whose proration_date is "" without raising Date::Error.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
api
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.