Skip to content

Self-heal stale membership plan slugs in getMembershipPlan#88

Merged
conatus merged 3 commits into
masterfrom
fix/membership-plan-slug-fallback
May 1, 2026
Merged

Self-heal stale membership plan slugs in getMembershipPlan#88
conatus merged 3 commits into
masterfrom
fix/membership-plan-slug-fallback

Conversation

@conatus
Copy link
Copy Markdown
Member

@conatus conatus commented May 1, 2026

Summary

A critical bug is currently preventing anyone from buying a membership tier on sites running v1.4.4+ of the plugin. The /stripe/create-subscription endpoint throws Selected plan is not in the list of plans, this is unexpected for every new sign-up. Reported live on tenantsunion.org.uk on 2026-05-01.

Root cause

Commit 0161e59 (v1.4.4, "Fix multi-currency without explicit plan IDs") changed Settings::getMembershipPlanId() to compose IDs from label_frequency_currency instead of just sanitize_title($label):

  • Before: low-wage-payment-level
  • After: low-wage-payment-level_monthly_gbp

The frontend dropdown began submitting the new-format ID immediately, but plans saved to wp_options before the upgrade still live under the old label-only key (ck_join_flow_membership_plan_low-wage-payment-level). Settings::getMembershipPlan() does a single get_option() lookup, finds nothing, returns false, and join.php:492 throws.

Plans are only re-keyed when an admin opens the Carbon Fields settings page and clicks Save (which calls Settings::saveMembershipPlans()). On every site that upgraded to 1.4.4+ without that step, sign-ups silently broke.

Renewals continued working because customer.subscription.updated / invoice.paid webhooks resolve plans via getMembershipPlanByPriceId (a Stripe price ID lookup, not a slug lookup), which is why the failure was hard to spot in the logs.

Fix

Make Settings::getMembershipPlan() self-heal across the slug-format change. After a direct get_option() miss, scan all ck_join_flow_membership_plan_* options, recompute each plan's ID via getMembershipPlanId(), and return the match. The fast path (direct hit) is preserved unchanged.

This means the plugin no longer requires a manual settings re-save to recover from the v1.4.4 upgrade, and protects against any future slug-format change.

conatus added 3 commits May 1, 2026 15:55
v1.4.4 (commit 0161e59) changed getMembershipPlanId() to compose IDs
from label_frequency_currency. The frontend now submits the new-format
ID, but plans saved before the upgrade still live in the WP options
table under the old label-only key. Until an admin re-saves the
settings page, /stripe/create-subscription throws "Selected plan is
not in the list of plans" and no one can buy a membership.

Make getMembershipPlan() fall back to scanning all
ck_join_flow_membership_plan_* options and matching by recomputed ID.
Test pins the production failure mode and the negative-match guard.
@conatus conatus merged commit 895b3a4 into master May 1, 2026
3 checks passed
@conatus conatus deleted the fix/membership-plan-slug-fallback branch May 1, 2026 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant