s2Member-Profile crashes for Stripe account - Log & Patch included

Hi @clavaque ,

Hope you are well.

I just started having an account page crash in the shortcode [s2Member-Profile /].

Error log is below as is a patch for the code (which you should. of course, double-check :slight_smile:

AI assessment, which may not be accurate of course, was " The provided PHP function uses an outdated Stripe PHP SDK syntax ( $customer->subscriptions->retrieve() ) which was deprecated in v7.x and completely removed in v10.x+. In modern Stripe SDKs, you cannot retrieve a subscription directly as a property of a customer object. Instead, you must use the $stripe->subscriptions->retrieve() service method.".

==========
ERROR LOG

[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Util\CaseInsensitiveArray::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Util/CaseInsensitiveArray.php on line 45
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Util\CaseInsensitiveArray::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Util/CaseInsensitiveArray.php on line 57
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Util\CaseInsensitiveArray::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Util/CaseInsensitiveArray.php on line 35
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Util\CaseInsensitiveArray::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Util/CaseInsensitiveArray.php on line 51
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Util\CaseInsensitiveArray::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Util/CaseInsensitiveArray.php on line 25
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Util\CaseInsensitiveArray::getIterator() should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Util/CaseInsensitiveArray.php on line 30
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Util\Set::getIterator() should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Util/Set.php on line 41
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\StripeObject::offsetExists($k) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/StripeObject.php on line 187
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\StripeObject::offsetGet($k) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/StripeObject.php on line 197
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\StripeObject::offsetSet($k, $v) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/StripeObject.php on line 182
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\StripeObject::offsetUnset($k) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/StripeObject.php on line 192
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\StripeObject::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/StripeObject.php on line 203
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\StripeObject::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/StripeObject.php on line 403
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Return type of Stripe\Collection::getIterator() should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/Collection.php on line 112
[11-Aug-2026 00:00:08 UTC] PHP Deprecated: Creation of dynamic property Stripe\HttpClient\CurlClient::$randomGenerator is deprecated in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-sdk/lib/HttpClient/CurlClient.php on line 68
[11-Aug-2026 00:00:08 UTC] Stripe Notice: Undefined property of Stripe\Customer instance: subscriptions
[11-Aug-2026 00:00:08 UTC] PHP Fatal error: Uncaught Error: Call to a member function retrieve() on null in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-utilities.inc.php:565
Stack trace:
#0 /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-responses.inc.php(263): c_ws_plugin__s2member_pro_stripe_utilities::get_customer_subscription()
#1 /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-responses.inc.php(91): c_ws_plugin__s2member_pro_stripe_responses::stripe_form_attr_validation_errors()
#2 /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-form-in.inc.php(343): c_ws_plugin__s2member_pro_stripe_responses::stripe_update_response()
#3 /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-form.inc.php(63): c_ws_plugin__s2member_pro_stripe_form_in::sc_stripe_form()
#4 /var/www/wordpress/wp-includes/shortcodes.php(434): c_ws_plugin__s2member_pro_stripe_form::sc_stripe_form()
#5 [internal function]: do_shortcode_tag()
#6 /var/www/wordpress/wp-includes/shortcodes.php(273): preg_replace_callback()
#7 /var/www/wordpress/wp-includes/class-wp-hook.php(341): do_shortcode()
#8 /var/www/wordpress/wp-includes/plugin.php(205): WP_Hook->apply_filters()
#9 /var/www/wordpress/wp-includes/post-template.php(256): apply_filters()
#10 /var/www/wordpress/wp-content/themes/elegance/page.php(24): the_content()
#11 /var/www/wordpress/wp-includes/template-loader.php(132): include(’…’)
#12 /var/www/wordpress/wp-blog-header.php(19): require_once(’…’)
#13 /var/www/wordpress/index.php(17): require(’…’)
#14 {main}
thrown in /var/www/wordpress/wp-content/plugins/s2member-pro/src/includes/classes/gateways/stripe/stripe-utilities.inc.php on line 565

=============
TEMP PATCH

		public static function get_customer_subscription($customer_id, $subscription_id)
		{
			// Subscription IDs start with 'sub_', don't continue if not a sub ID.
			if (strpos($subscription_id, 'sub_') !== 0)
				return false;

			$input_time = time(); // Initialize.
			$input_vars = get_defined_vars(); // Arguments.

			self::init_stripe_sdk();
			
			try // Obtain existing customer object; else create a new one.
			{
//				$customer     = \Stripe\Customer::retrieve($customer_id);
//				$subscription = $customer->subscriptions->retrieve($subscription_id);
			
        		// TWH Patch Start 11Aug2026 - Modern SDK way to retrieve a subscription directly
       			$subscription = \Stripe\Subscription::retrieve($subscription_id);
      			// Ensure the subscription actually belongs to the requested customer
     			if ($subscription->customer !== $customer_id) {
     			       throw new \Exception("Subscription does not belong to this customer.");
     			}
                // TWH Patch End 11Aug2026
 
				self::log_entry(__FUNCTION__, $input_time, $input_vars, time(), $subscription);

				return $subscription; // Stripe subscription object.
			}
			catch(exception $exception)
			{
				self::log_entry(__FUNCTION__, $input_time, $input_vars, time(), $exception);

				return self::error_message($exception);
			}
		}

========
Cheers,
Tim

3 Likes

Interesting patch, I’ve applied it to a low traffic website and so far there are no issues

Useful feedback…you had the issue as well?

I don’t think so but I’ll check my logs in a few days or a week to see if there is any issues before or after.

Hi Tim!

Thank you for the report, logs, and patch. I reviewed this and changed s2Member to retrieve the Stripe subscription directly, as in your patch, with an additional check that the subscription belongs to the expected Stripe customer.

This is fixed in v260829. I also addressed the PHP 8.5 deprecation notices from the bundled Stripe SDK that were showing in your log.

:slight_smile: