Describe the bug
When retrieving a customer via $stripe->customers->retrieve($id), Stripe returns a stub {id, deleted: true} object if the customer was deleted — this is documented API behavior.
However, the SDK's Stripe\Customer class does not declare $deleted as a @property, which forces consumers using PHPStan/Psalm to add @phpstan-ignore property.notFound around the check:
$customer = $stripe->customers->retrieve($user->stripe_id);
/** @phpstan-ignore property.notFound */
if (isset($customer->deleted) && $customer->deleted === true) {
// handle deleted customer — clear local reference, recreate, etc.
}
To Reproduce
- Call
$stripe->customers->retrieve(...) on a customer you deleted.
- Static-analyze the return with PHPStan on
max level.
- Observe
Access to an undefined property Stripe\Customer::$deleted.
Verified on stripe/stripe-php v17.6.0 and checked the stubs on master as of April 2026 — $deleted is still absent on Customer.
Expected behavior
Either:
-
Add @property null|bool \$deleted to Stripe\Customer (simplest, matches the existing pattern used by Apps\Secret), or
-
Model the deleted-customer response as a distinct DeletedCustomer class and reflect that in CustomerService::retrieve()'s return type (\Stripe\Customer|\Stripe\DeletedCustomer). This would be the most explicit, but it's a breaking-ish change for static analyzers that would require every consumer to narrow the union.
Option 1 is the pragmatic fix — no runtime change, just a docblock addition that accurately describes the API contract.
Context
Workaround
Add a one-line `@phpstan-ignore property.notFound` above the check. Works, but every library consumer hits it on first encounter.
Describe the bug
When retrieving a customer via
$stripe->customers->retrieve($id), Stripe returns a stub{id, deleted: true}object if the customer was deleted — this is documented API behavior.However, the SDK's
Stripe\Customerclass does not declare$deletedas a@property, which forces consumers using PHPStan/Psalm to add@phpstan-ignore property.notFoundaround the check:To Reproduce
$stripe->customers->retrieve(...)on a customer you deleted.maxlevel.Access to an undefined property Stripe\Customer::$deleted.Verified on
stripe/stripe-phpv17.6.0 and checked the stubs onmasteras of April 2026 —$deletedis still absent onCustomer.Expected behavior
Either:
Add
@property null|bool \$deletedtoStripe\Customer(simplest, matches the existing pattern used byApps\Secret), orModel the deleted-customer response as a distinct
DeletedCustomerclass and reflect that inCustomerService::retrieve()'s return type (\Stripe\Customer|\Stripe\DeletedCustomer). This would be the most explicit, but it's a breaking-ish change for static analyzers that would require every consumer to narrow the union.Option 1 is the pragmatic fix — no runtime change, just a docblock addition that accurately describes the API contract.
Context
Workaround
Add a one-line `@phpstan-ignore property.notFound` above the check. Works, but every library consumer hits it on first encounter.