Skip to content

[BUG] Undefined method 'payment_intent' error when syncing older Stripe subscriptions #1182

@marckohlbrugge

Description

@marckohlbrugge

I'm experiencing an undefined method 'payment_intent' error in Pay 11.1.1 when syncing older Stripe subscriptions.

The Error

gems/stripe-15.3.0/lib/stripe/stripe_object.rb:417:in `Stripe::StripeObject#method_missing': undefined method 'payment_intent' for #<Stripe::StripeObject:0x00007a3334feabf0> (NoMethodError)
    from gems/pay-11.1.1/app/models/pay/stripe/subscription.rb:106:in `block in Pay::Stripe::Subscription.sync'
    from gems/pay-11.1.1/app/models/pay/stripe/subscription.rb:104:in `Array#each'
    from gems/pay-11.1.1/app/models/pay/stripe/subscription.rb:104:in `Pay::Stripe::Subscription.sync'
    from gems/pay-11.1.1/app/models/pay/stripe/customer.rb:154:in `block in Pay::Stripe::Customer#sync_subscriptions'

The Problem

Location: pay-11.1.1/app/models/pay/stripe/subscription.rb:104-107

The code assumes a nested structure that doesn't exist in Stripe's API:

Array(invoice.try(:payments)).each do |invoice_payment|
  next unless invoice_payment.status == "paid"
  Pay::Stripe::Charge.sync_payment_intent(invoice_payment.payment.payment_intent, stripe_account: pay_subscription.stripe_account)
end

The code tries to access invoice_payment.payment.payment_intent, but:

  • For some invoices (especially older ones from 2018-2019), invoice.payments returns nil
  • When payments do exist, they don't have a nested .payment property
  • The code expects invoice_payment.payment.payment_intent but this structure doesn't match Stripe's API

Environment

  • Pay gem version: 11.1.1
  • Stripe gem version: 15.3.0
  • Ruby version: 3.4.2
  • Rails version: 8.0.2

How to reproduce

  1. Have a user with an older Stripe subscription (especially from 2018-2019)
  2. Call user.payment_processor.sync_subscriptions(status: "all")
  3. The error occurs when processing invoice payments

Example subscription that triggers this:

  • Subscription ID: sub_DqVLKzsG0JzYO9 (canceled, from 2018)
  • Invoice ID: in_1E2xmHJCY2L6VQsLEEaoHvbA
  • invoice.payments returns nil

Note: This issue appears to primarily affect older subscriptions. The Stripe API response structure for invoices has evolved over time, and older invoices might not have the payments array or payment intent data that the Pay gem expects. Payment Intents were introduced by Stripe in 2018-2019, so invoices before that time won't have this data.

Temporary Workaround

Create config/initializers/pay_stripe_subscription_patch.rb:

module PayStripeSubscriptionPatch
  def sync(object = nil, **options)
    super
  rescue NoMethodError => e
    if e.message.include?("payment_intent")
      Rails.logger.warn "Pay gem bug: #{e.message}. Skipping payment intent sync."
      # Continue without the payment intent processing
      # The subscription will still be synced, just without the payment intent data
      pay_subscription
    else
      raise
    end
  end
end

Rails.application.config.after_initialize do
  if defined?(Pay::Stripe::Subscription)
    Pay::Stripe::Subscription.singleton_class.prepend(PayStripeSubscriptionPatch)
  end
end

Suggested Fix

The code should handle cases where:

  1. invoice.payments is nil
  2. Payment objects don't have the expected nested structure
  3. Older invoices that predate Payment Intents

Possible solutions:

  • Add nil checks before accessing nested properties
  • Check the invoice date or API version to determine if payment intents are available
  • Gracefully skip payment intent sync for invoices that don't support it

Related Issues

This appears to be similar to #1123 where there was a method_missing error with Stripe objects not having expected methods.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions