A subscription is created without completing payment #1891

Closed
opened 2026-03-13 09:11:02 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @fabriziofeitosa on GitHub (Sep 9, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. I created three different buttons that call the authClient.subscription.upgrade() function, each with its own settings.
  2. I click any of the buttons and purchase, then proceed to checkout.
  3. I press the back button in the Stripe checkout.
  4. After returning, I choose a different subscription plan.
  5. I return again. A subscription is recorded as active in the database even without having completed the purchase. Some columns have empty values.

Current vs. Expected behavior

When I try to select a plan I've previously clicked:
Image

Record created in the database after clicking "back" for the second time:
Image

What version of Better Auth are you using?

1.3.9

System info

{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 11 Pro",
    "release": "10.0.26100",
    "cpuCount": 12,
    "cpuModel": "AMD Ryzen 5 5600X 6-Core Processor             ",
    "totalMemory": "31.91 GB",
    "freeMemory": "4.76 GB"
  },
  "node": {
    "version": "v22.16.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "11.4.2"
  },
  "frameworks": [
    {
      "name": "next",
      "version": "15.5.2"
    },
    {
      "name": "react",
      "version": "19.1.0"
    }
  ],
  "databases": [
    {
      "name": "@prisma/client",
      "version": "^6.14.0"
    }
  ],
  "betterAuth": {
    "version": "0.1.0",
    "config": {
      "trustedOrigins": [
        "http://localhost:3000",
        "https://sosprev.com/",
        "https://sos-prev.up.railway.app"
      ],
      "session": {
        "expiresIn": 86400,
        "updateAge": 86400,
        "additionalFields": {
          "subscriptionStatus": {
            "type": "string",
            "required": false
          }
        }
      },
      "account": {
        "accountLinking": {
          "enabled": true,
          "trustedProviders": [
            "google"
          ]
        }
      },
      "emailAndPassword": {
        "enabled": true,
        "requireEmailVerification": false
      },
      "emailVerification": {
        "sendOnSignUp": true,
        "autoSignInAfterVerification": true
      },
      "socialProviders": {
        "google": {
          "prompt": "select_account",
          "clientId": "[REDACTED]",
          "clientSecret": "[REDACTED]"
        }
      },
      "plugins": [
        {
          "name": "organization",
          "config": {
            "id": "organization",
            "endpoints": {},
            "schema": {
              "organization": {
                "fields": {
                  "name": {
                    "type": "string",
                    "required": true,
                    "sortable": true
                  },
                  "slug": {
                    "type": "string",
                    "unique": true,
                    "sortable": true
                  },
                  "logo": {
                    "type": "string",
                    "required": false
                  },
                  "createdAt": {
                    "type": "date",
                    "required": true
                  },
                  "metadata": {
                    "type": "string",
                    "required": false
                  }
                }
              },
              "member": {
                "fields": {
                  "organizationId": {
                    "type": "string",
                    "required": true,
                    "references": {
                      "model": "organization",
                      "field": "id"
                    }
                  },
                  "userId": {
                    "type": "string",
                    "required": true,
                    "references": {
                      "model": "user",
                      "field": "id"
                    }
                  },
                  "role": {
                    "type": "string",
                    "required": true,
                    "sortable": true,
                    "defaultValue": "member"
                  },
                  "createdAt": {
                    "type": "date",
                    "required": true
                  }
                }
              },
              "invitation": {
                "fields": {
                  "organizationId": {
                    "type": "string",
                    "required": true,
                    "references": {
                      "model": "organization",
                      "field": "id"
                    }
                  },
                  "email": {
                    "type": "string",
                    "required": true,
                    "sortable": true
                  },
                  "role": {
                    "type": "string",
                    "required": false,
                    "sortable": true
                  },
                  "status": {
                    "type": "string",
                    "required": true,
                    "sortable": true,
                    "defaultValue": "pending"
                  },
                  "expiresAt": {
                    "type": "date",
                    "required": true
                  },
                  "inviterId": {
                    "type": "string",
                    "references": {
                      "model": "user",
                      "field": "id"
                    },
                    "required": true
                  }
                }
              },
              "session": {
                "fields": {
                  "activeOrganizationId": {
                    "type": "string",
                    "required": false
                  }
                }
              }
            },
            "$Infer": {
              "Organization": {},
              "Invitation": {},
              "Member": {},
              "Team": {},
              "TeamMember": {},
              "ActiveOrganization": {}
            },
            "$ERROR_CODES": {
              "YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_ORGANIZATION": "You are not allowed to create a new organization",
              "YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_ORGANIZATIONS": "You have reached the maximum number of organizations",
              "ORGANIZATION_ALREADY_EXISTS": "Organization already exists",
              "ORGANIZATION_NOT_FOUND": "Organization not found",
              "USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION": "User is not a member of the organization",
              "YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_ORGANIZATION": "You are not allowed to update this organization",
              "YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_ORGANIZATION": "You are not allowed to delete this organization",
              "NO_ACTIVE_ORGANIZATION": "No active organization",
              "USER_IS_ALREADY_A_MEMBER_OF_THIS_ORGANIZATION": "User is already a member of this organization",
              "MEMBER_NOT_FOUND": "Member not found",
              "ROLE_NOT_FOUND": "Role not found",
              "YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_TEAM": "You are not allowed to create a new team",
              "TEAM_ALREADY_EXISTS": "Team already exists",
              "TEAM_NOT_FOUND": "Team not found",
              "YOU_CANNOT_LEAVE_THE_ORGANIZATION_AS_THE_ONLY_OWNER": "You cannot leave the organization as the only owner",
              "YOU_CANNOT_LEAVE_THE_ORGANIZATION_WITHOUT_AN_OWNER": "You cannot leave the organization without an owner",
              "YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_MEMBER": "You are not allowed to delete this member",
              "YOU_ARE_NOT_ALLOWED_TO_INVITE_USERS_TO_THIS_ORGANIZATION": "You are not allowed to invite users to this organization",
              "USER_IS_ALREADY_INVITED_TO_THIS_ORGANIZATION": "User is already invited to this organization",
              "INVITATION_NOT_FOUND": "Invitation not found",
              "YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION": "You are not the recipient of the invitation",
              "EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION": "Email verification required before accepting or rejecting invitation",
              "YOU_ARE_NOT_ALLOWED_TO_CANCEL_THIS_INVITATION": "You are not allowed to cancel this invitation",
              "INVITER_IS_NO_LONGER_A_MEMBER_OF_THE_ORGANIZATION": "Inviter is no longer a member of the organization",
              "YOU_ARE_NOT_ALLOWED_TO_INVITE_USER_WITH_THIS_ROLE": "You are not allowed to invite a user with this role",
              "FAILED_TO_RETRIEVE_INVITATION": "Failed to retrieve invitation",       
              "YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_TEAMS": "You have reached the maximum number of teams",
              "UNABLE_TO_REMOVE_LAST_TEAM": "Unable to remove last team",
              "YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_MEMBER": "You are not allowed to update this member",
              "ORGANIZATION_MEMBERSHIP_LIMIT_REACHED": "Organization membership limit reached",
              "YOU_ARE_NOT_ALLOWED_TO_CREATE_TEAMS_IN_THIS_ORGANIZATION": "You are not allowed to create teams in this organization",
              "YOU_ARE_NOT_ALLOWED_TO_DELETE_TEAMS_IN_THIS_ORGANIZATION": "You are not allowed to delete teams in this organization",
              "YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_TEAM": "You are not allowed to update this team",
              "YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_TEAM": "You are not allowed to delete this team",
              "INVITATION_LIMIT_REACHED": "Invitation limit reached",
              "TEAM_MEMBER_LIMIT_REACHED": "Team member limit reached",
              "USER_IS_NOT_A_MEMBER_OF_THE_TEAM": "User is not a member of the team", 
              "YOU_CAN_NOT_ACCESS_THE_MEMBERS_OF_THIS_TEAM": "You are not allowed to list the members of this team",
              "YOU_DO_NOT_HAVE_AN_ACTIVE_TEAM": "You do not have an active team",     
              "YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_TEAM_MEMBER": "You are not allowed to create a new member",
              "YOU_ARE_NOT_ALLOWED_TO_REMOVE_A_TEAM_MEMBER": "You are not allowed to remove a team member",
              "YOU_ARE_NOT_ALLOWED_TO_ACCESS_THIS_ORGANIZATION": "You are not allowed to access this organization as an owner",
              "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION": "You are not a member of this organization"
            },
            "options": {
              "organizationLimit": 1,
              "ac": {
                "statements": {
                  "user": [
                    "create",
                    "list",
                    "set-role",
                    "ban",
                    "impersonate",
                    "delete",
                    "set-password",
                    "get",
                    "update"
                  ],
                  "session": [
                    "list",
                    "revoke",
                    "delete"
                  ],
                  "cases": [
                    "create",
                    "share",
                    "update",
                    "delete"
                  ],
                  "organization": [
                    "update",
                    "delete"
                  ],
                  "member": [
                    "create",
                    "update",
                    "delete"
                  ],
                  "invitation": [
                    "create",
                    "cancel"
                  ],
                  "settings": [
                    "create",
                    "share",
                    "update",
                    "delete"
                  ]
                }
              },
              "roles": {
                "owner": {
                  "statements": {
                    "cases": [
                      "create",
                      "share",
                      "update",
                      "delete"
                    ],
                    "organization": [
                      "update",
                      "delete"
                    ],
                    "member": [
                      "create",
                      "update",
                      "delete"
                    ],
                    "invitation": [
                      "create",
                      "cancel"
                    ]
                  }
                },
                "admin": {
                  "statements": {
                    "user": [
                      "create",
                      "list",
                      "set-role",
                      "ban",
                      "impersonate",
                      "delete",
                      "set-password",
                      "get",
                      "update"
                    ],
                    "session": [
                      "list",
                      "revoke",
                      "delete"
                    ],
                    "cases": [
                      "create",
                      "share",
                      "update",
                      "delete"
                    ],
                    "settings": [
                      "create",
                      "share",
                      "update"
                    ],
                    "organization": [
                      "update",
                      "delete"
                    ],
                    "member": [
                      "create",
                      "update",
                      "delete"
                    ],
                    "invitation": [
                      "create",
                      "cancel"
                    ]
                  }
                },
                "member": {
                  "statements": {
                    "cases": [
                      "create",
                      "share",
                      "update"
                    ]
                  }
                }
              }
            }
          }
        },
        {
          "name": "admin",
          "config": {
            "id": "admin",
            "hooks": {
              "after": [
                {}
              ]
            },
            "endpoints": {},
            "$ERROR_CODES": {
              "FAILED_TO_CREATE_USER": "Failed to create user",
              "USER_ALREADY_EXISTS": "User already exists. Use another email.",       
              "YOU_CANNOT_BAN_YOURSELF": "You cannot ban yourself",
              "YOU_ARE_NOT_ALLOWED_TO_CHANGE_USERS_ROLE": "You are not allowed to change users role",
              "YOU_ARE_NOT_ALLOWED_TO_CREATE_USERS": "You are not allowed to create users",
              "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS": "You are not allowed to list users",
              "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS_SESSIONS": "You are not allowed to list users sessions",
              "YOU_ARE_NOT_ALLOWED_TO_BAN_USERS": "You are not allowed to ban users", 
              "YOU_ARE_NOT_ALLOWED_TO_IMPERSONATE_USERS": "You are not allowed to impersonate users",
              "YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS": "You are not allowed to revoke users sessions",
              "YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS": "You are not allowed to delete users",
              "YOU_ARE_NOT_ALLOWED_TO_SET_USERS_PASSWORD": "[REDACTED]",
              "BANNED_USER": "You have been banned from this application",
              "YOU_ARE_NOT_ALLOWED_TO_GET_USER": "You are not allowed to get user",   
              "NO_DATA_TO_UPDATE": "No data to update",
              "YOU_ARE_NOT_ALLOWED_TO_UPDATE_USERS": "You are not allowed to update users",
              "YOU_CANNOT_REMOVE_YOURSELF": "You cannot remove yourself"
            },
            "schema": {
              "user": {
                "fields": {
                  "role": {
                    "type": "string",
                    "required": false,
                    "input": false
                  },
                  "banned": {
                    "type": "boolean",
                    "defaultValue": false,
                    "required": false,
                    "input": false
                  },
                  "banReason": {
                    "type": "string",
                    "required": false,
                    "input": false
                  },
                  "banExpires": {
                    "type": "date",
                    "required": false,
                    "input": false
                  }
                }
              },
              "session": {
                "fields": {
                  "impersonatedBy": {
                    "type": "string",
                    "required": false
                  }
                }
              }
            },
            "options": {
              "bannedUserMessage": "Você foi banido do sistema. Entre em contato com o administrador.",
              "ac": {
                "statements": {
                  "user": [
                    "create",
                    "list",
                    "set-role",
                    "ban",
                    "impersonate",
                    "delete",
                    "set-password",
                    "get",
                    "update"
                  ],
                  "session": [
                    "list",
                    "revoke",
                    "delete"
                  ],
                  "cases": [
                    "create",
                    "share",
                    "update",
                    "delete"
                  ],
                  "organization": [
                    "update",
                    "delete"
                  ],
                  "member": [
                    "create",
                    "update",
                    "delete"
                  ],
                  "invitation": [
                    "create",
                    "cancel"
                  ],
                  "settings": [
                    "create",
                    "share",
                    "update",
                    "delete"
                  ]
                }
              },
              "roles": {
                "admin": {
                  "statements": {
                    "user": [
                      "create",
                      "list",
                      "set-role",
                      "ban",
                      "impersonate",
                      "delete",
                      "set-password",
                      "get",
                      "update"
                    ],
                    "session": [
                      "list",
                      "revoke",
                      "delete"
                    ],
                    "cases": [
                      "create",
                      "share",
                      "update",
                      "delete"
                    ],
                    "settings": [
                      "create",
                      "share",
                      "update"
                    ],
                    "organization": [
                      "update",
                      "delete"
                    ],
                    "member": [
                      "create",
                      "update",
                      "delete"
                    ],
                    "invitation": [
                      "create",
                      "cancel"
                    ]
                  }
                },
                "superadmin": {
                  "statements": {
                    "user": [
                      "create",
                      "list",
                      "set-role",
                      "ban",
                      "impersonate",
                      "delete",
                      "set-password",
                      "get",
                      "update"
                    ],
                    "session": [
                      "list",
                      "revoke",
                      "delete"
                    ],
                    "cases": [
                      "create",
                      "share",
                      "update",
                      "delete"
                    ],
                    "settings": [
                      "create",
                      "share",
                      "update",
                      "delete"
                    ],
                    "organization": [
                      "update",
                      "delete"
                    ],
                    "member": [
                      "create",
                      "update",
                      "delete"
                    ],
                    "invitation": [
                      "create",
                      "cancel"
                    ]
                  }
                },
                "user": {
                  "statements": {
                    "cases": [
                      "create",
                      "share",
                      "update"
                    ]
                  }
                }
              }
            }
          }
        },
        {
          "name": "stripe",
          "config": {
            "id": "stripe",
            "endpoints": {},
            "schema": {
              "subscription": {
                "fields": {
                  "plan": {
                    "type": "string",
                    "required": true
                  },
                  "referenceId": {
                    "type": "string",
                    "required": true
                  },
                  "stripeCustomerId": {
                    "type": "string",
                    "required": false
                  },
                  "stripeSubscriptionId": {
                    "type": "string",
                    "required": false
                  },
                  "status": {
                    "type": "string",
                    "defaultValue": "incomplete"
                  },
                  "periodStart": {
                    "type": "date",
                    "required": false
                  },
                  "periodEnd": {
                    "type": "date",
                    "required": false
                  },
                  "cancelAtPeriodEnd": {
                    "type": "boolean",
                    "required": false,
                    "defaultValue": false
                  },
                  "seats": {
                    "type": "number",
                    "required": false
                  }
                }
              },
              "user": {
                "fields": {
                  "stripeCustomerId": {
                    "type": "string",
                    "required": false
                  }
                }
              }
            }
          }
        },
        {
          "name": "captcha",
          "config": {
            "id": "captcha"
          }
        }
      ],
      "databaseHooks": {
        "session": {
          "create": {}
        }
      },
      "hooks": {}
    }
  }
}

Which area(s) are affected? (Select all that apply)

Backend, Client

Auth config (if applicable)

stripe({
      stripeClient,
      stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
      createCustomerOnSignUp: false,
      subscription: {
        enabled: true,
        requireEmailVerification: false,
        plans: async () => {
          const plans = await prisma.activeStripePlans.findMany();

          if (!plans) return [];

          return plans.map((plan) => ({
            name: plan.name,
            priceId: plan.priceId,
            annualDiscountPriceId: plan.annualDiscountPriceId ?? undefined,
            limits: plan.limits as Record<string, number> | undefined,
          }));
        },
        authorizeReference: async ({ user, session, referenceId, action }) => {
          // Check if the user has permission to manage subscriptions for this reference
          if (
            action === "upgrade-subscription" ||
            action === "cancel-subscription" ||
            action === "restore-subscription"
          ) {
            const org = await prisma.member.findFirst({
              where: {
                organizationId: referenceId,
                userId: user.id,
              },
            });
            return org?.role === "owner" || org?.role === "admin";
          }
          return true;
        },
        getCheckoutSessionParams: async (
          { user, session, plan, subscription },
          request,
        ) => {
          return {
            params: {
              allow_promotion_codes: true,
            },
          };
        },
      },
    }),

Additional context

This is a scenario where the user cancels a plan and chooses another. When they think better and press "back," they are receiving an active plan without completing the purchase.

Originally created by @fabriziofeitosa on GitHub (Sep 9, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. I created three different buttons that call the `authClient.subscription.upgrade()` function, each with its own settings. 2. I click any of the buttons and purchase, then proceed to checkout. 3. I press the back button in the Stripe checkout. 4. After returning, I choose a different subscription plan. 5. I return again. A subscription is recorded as `active` in the database even without having completed the purchase. Some columns have empty values. ### Current vs. Expected behavior When I try to select a plan I've previously clicked: <img width="396" height="104" alt="Image" src="https://github.com/user-attachments/assets/c4e4b96c-e115-407a-8509-42b3449d1583" /> Record created in the database after clicking "back" for the second time: <img width="1699" height="158" alt="Image" src="https://github.com/user-attachments/assets/2eb35b29-36f5-44bf-9cc0-d03ea0cfd602" /> ### What version of Better Auth are you using? 1.3.9 ### System info ```bash { "system": { "platform": "win32", "arch": "x64", "version": "Windows 11 Pro", "release": "10.0.26100", "cpuCount": 12, "cpuModel": "AMD Ryzen 5 5600X 6-Core Processor ", "totalMemory": "31.91 GB", "freeMemory": "4.76 GB" }, "node": { "version": "v22.16.0", "env": "development" }, "packageManager": { "name": "npm", "version": "11.4.2" }, "frameworks": [ { "name": "next", "version": "15.5.2" }, { "name": "react", "version": "19.1.0" } ], "databases": [ { "name": "@prisma/client", "version": "^6.14.0" } ], "betterAuth": { "version": "0.1.0", "config": { "trustedOrigins": [ "http://localhost:3000", "https://sosprev.com/", "https://sos-prev.up.railway.app" ], "session": { "expiresIn": 86400, "updateAge": 86400, "additionalFields": { "subscriptionStatus": { "type": "string", "required": false } } }, "account": { "accountLinking": { "enabled": true, "trustedProviders": [ "google" ] } }, "emailAndPassword": { "enabled": true, "requireEmailVerification": false }, "emailVerification": { "sendOnSignUp": true, "autoSignInAfterVerification": true }, "socialProviders": { "google": { "prompt": "select_account", "clientId": "[REDACTED]", "clientSecret": "[REDACTED]" } }, "plugins": [ { "name": "organization", "config": { "id": "organization", "endpoints": {}, "schema": { "organization": { "fields": { "name": { "type": "string", "required": true, "sortable": true }, "slug": { "type": "string", "unique": true, "sortable": true }, "logo": { "type": "string", "required": false }, "createdAt": { "type": "date", "required": true }, "metadata": { "type": "string", "required": false } } }, "member": { "fields": { "organizationId": { "type": "string", "required": true, "references": { "model": "organization", "field": "id" } }, "userId": { "type": "string", "required": true, "references": { "model": "user", "field": "id" } }, "role": { "type": "string", "required": true, "sortable": true, "defaultValue": "member" }, "createdAt": { "type": "date", "required": true } } }, "invitation": { "fields": { "organizationId": { "type": "string", "required": true, "references": { "model": "organization", "field": "id" } }, "email": { "type": "string", "required": true, "sortable": true }, "role": { "type": "string", "required": false, "sortable": true }, "status": { "type": "string", "required": true, "sortable": true, "defaultValue": "pending" }, "expiresAt": { "type": "date", "required": true }, "inviterId": { "type": "string", "references": { "model": "user", "field": "id" }, "required": true } } }, "session": { "fields": { "activeOrganizationId": { "type": "string", "required": false } } } }, "$Infer": { "Organization": {}, "Invitation": {}, "Member": {}, "Team": {}, "TeamMember": {}, "ActiveOrganization": {} }, "$ERROR_CODES": { "YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_ORGANIZATION": "You are not allowed to create a new organization", "YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_ORGANIZATIONS": "You have reached the maximum number of organizations", "ORGANIZATION_ALREADY_EXISTS": "Organization already exists", "ORGANIZATION_NOT_FOUND": "Organization not found", "USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION": "User is not a member of the organization", "YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_ORGANIZATION": "You are not allowed to update this organization", "YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_ORGANIZATION": "You are not allowed to delete this organization", "NO_ACTIVE_ORGANIZATION": "No active organization", "USER_IS_ALREADY_A_MEMBER_OF_THIS_ORGANIZATION": "User is already a member of this organization", "MEMBER_NOT_FOUND": "Member not found", "ROLE_NOT_FOUND": "Role not found", "YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_TEAM": "You are not allowed to create a new team", "TEAM_ALREADY_EXISTS": "Team already exists", "TEAM_NOT_FOUND": "Team not found", "YOU_CANNOT_LEAVE_THE_ORGANIZATION_AS_THE_ONLY_OWNER": "You cannot leave the organization as the only owner", "YOU_CANNOT_LEAVE_THE_ORGANIZATION_WITHOUT_AN_OWNER": "You cannot leave the organization without an owner", "YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_MEMBER": "You are not allowed to delete this member", "YOU_ARE_NOT_ALLOWED_TO_INVITE_USERS_TO_THIS_ORGANIZATION": "You are not allowed to invite users to this organization", "USER_IS_ALREADY_INVITED_TO_THIS_ORGANIZATION": "User is already invited to this organization", "INVITATION_NOT_FOUND": "Invitation not found", "YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION": "You are not the recipient of the invitation", "EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION": "Email verification required before accepting or rejecting invitation", "YOU_ARE_NOT_ALLOWED_TO_CANCEL_THIS_INVITATION": "You are not allowed to cancel this invitation", "INVITER_IS_NO_LONGER_A_MEMBER_OF_THE_ORGANIZATION": "Inviter is no longer a member of the organization", "YOU_ARE_NOT_ALLOWED_TO_INVITE_USER_WITH_THIS_ROLE": "You are not allowed to invite a user with this role", "FAILED_TO_RETRIEVE_INVITATION": "Failed to retrieve invitation", "YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_TEAMS": "You have reached the maximum number of teams", "UNABLE_TO_REMOVE_LAST_TEAM": "Unable to remove last team", "YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_MEMBER": "You are not allowed to update this member", "ORGANIZATION_MEMBERSHIP_LIMIT_REACHED": "Organization membership limit reached", "YOU_ARE_NOT_ALLOWED_TO_CREATE_TEAMS_IN_THIS_ORGANIZATION": "You are not allowed to create teams in this organization", "YOU_ARE_NOT_ALLOWED_TO_DELETE_TEAMS_IN_THIS_ORGANIZATION": "You are not allowed to delete teams in this organization", "YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_TEAM": "You are not allowed to update this team", "YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_TEAM": "You are not allowed to delete this team", "INVITATION_LIMIT_REACHED": "Invitation limit reached", "TEAM_MEMBER_LIMIT_REACHED": "Team member limit reached", "USER_IS_NOT_A_MEMBER_OF_THE_TEAM": "User is not a member of the team", "YOU_CAN_NOT_ACCESS_THE_MEMBERS_OF_THIS_TEAM": "You are not allowed to list the members of this team", "YOU_DO_NOT_HAVE_AN_ACTIVE_TEAM": "You do not have an active team", "YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_TEAM_MEMBER": "You are not allowed to create a new member", "YOU_ARE_NOT_ALLOWED_TO_REMOVE_A_TEAM_MEMBER": "You are not allowed to remove a team member", "YOU_ARE_NOT_ALLOWED_TO_ACCESS_THIS_ORGANIZATION": "You are not allowed to access this organization as an owner", "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION": "You are not a member of this organization" }, "options": { "organizationLimit": 1, "ac": { "statements": { "user": [ "create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update" ], "session": [ "list", "revoke", "delete" ], "cases": [ "create", "share", "update", "delete" ], "organization": [ "update", "delete" ], "member": [ "create", "update", "delete" ], "invitation": [ "create", "cancel" ], "settings": [ "create", "share", "update", "delete" ] } }, "roles": { "owner": { "statements": { "cases": [ "create", "share", "update", "delete" ], "organization": [ "update", "delete" ], "member": [ "create", "update", "delete" ], "invitation": [ "create", "cancel" ] } }, "admin": { "statements": { "user": [ "create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update" ], "session": [ "list", "revoke", "delete" ], "cases": [ "create", "share", "update", "delete" ], "settings": [ "create", "share", "update" ], "organization": [ "update", "delete" ], "member": [ "create", "update", "delete" ], "invitation": [ "create", "cancel" ] } }, "member": { "statements": { "cases": [ "create", "share", "update" ] } } } } } }, { "name": "admin", "config": { "id": "admin", "hooks": { "after": [ {} ] }, "endpoints": {}, "$ERROR_CODES": { "FAILED_TO_CREATE_USER": "Failed to create user", "USER_ALREADY_EXISTS": "User already exists. Use another email.", "YOU_CANNOT_BAN_YOURSELF": "You cannot ban yourself", "YOU_ARE_NOT_ALLOWED_TO_CHANGE_USERS_ROLE": "You are not allowed to change users role", "YOU_ARE_NOT_ALLOWED_TO_CREATE_USERS": "You are not allowed to create users", "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS": "You are not allowed to list users", "YOU_ARE_NOT_ALLOWED_TO_LIST_USERS_SESSIONS": "You are not allowed to list users sessions", "YOU_ARE_NOT_ALLOWED_TO_BAN_USERS": "You are not allowed to ban users", "YOU_ARE_NOT_ALLOWED_TO_IMPERSONATE_USERS": "You are not allowed to impersonate users", "YOU_ARE_NOT_ALLOWED_TO_REVOKE_USERS_SESSIONS": "You are not allowed to revoke users sessions", "YOU_ARE_NOT_ALLOWED_TO_DELETE_USERS": "You are not allowed to delete users", "YOU_ARE_NOT_ALLOWED_TO_SET_USERS_PASSWORD": "[REDACTED]", "BANNED_USER": "You have been banned from this application", "YOU_ARE_NOT_ALLOWED_TO_GET_USER": "You are not allowed to get user", "NO_DATA_TO_UPDATE": "No data to update", "YOU_ARE_NOT_ALLOWED_TO_UPDATE_USERS": "You are not allowed to update users", "YOU_CANNOT_REMOVE_YOURSELF": "You cannot remove yourself" }, "schema": { "user": { "fields": { "role": { "type": "string", "required": false, "input": false }, "banned": { "type": "boolean", "defaultValue": false, "required": false, "input": false }, "banReason": { "type": "string", "required": false, "input": false }, "banExpires": { "type": "date", "required": false, "input": false } } }, "session": { "fields": { "impersonatedBy": { "type": "string", "required": false } } } }, "options": { "bannedUserMessage": "Você foi banido do sistema. Entre em contato com o administrador.", "ac": { "statements": { "user": [ "create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update" ], "session": [ "list", "revoke", "delete" ], "cases": [ "create", "share", "update", "delete" ], "organization": [ "update", "delete" ], "member": [ "create", "update", "delete" ], "invitation": [ "create", "cancel" ], "settings": [ "create", "share", "update", "delete" ] } }, "roles": { "admin": { "statements": { "user": [ "create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update" ], "session": [ "list", "revoke", "delete" ], "cases": [ "create", "share", "update", "delete" ], "settings": [ "create", "share", "update" ], "organization": [ "update", "delete" ], "member": [ "create", "update", "delete" ], "invitation": [ "create", "cancel" ] } }, "superadmin": { "statements": { "user": [ "create", "list", "set-role", "ban", "impersonate", "delete", "set-password", "get", "update" ], "session": [ "list", "revoke", "delete" ], "cases": [ "create", "share", "update", "delete" ], "settings": [ "create", "share", "update", "delete" ], "organization": [ "update", "delete" ], "member": [ "create", "update", "delete" ], "invitation": [ "create", "cancel" ] } }, "user": { "statements": { "cases": [ "create", "share", "update" ] } } } } } }, { "name": "stripe", "config": { "id": "stripe", "endpoints": {}, "schema": { "subscription": { "fields": { "plan": { "type": "string", "required": true }, "referenceId": { "type": "string", "required": true }, "stripeCustomerId": { "type": "string", "required": false }, "stripeSubscriptionId": { "type": "string", "required": false }, "status": { "type": "string", "defaultValue": "incomplete" }, "periodStart": { "type": "date", "required": false }, "periodEnd": { "type": "date", "required": false }, "cancelAtPeriodEnd": { "type": "boolean", "required": false, "defaultValue": false }, "seats": { "type": "number", "required": false } } }, "user": { "fields": { "stripeCustomerId": { "type": "string", "required": false } } } } } }, { "name": "captcha", "config": { "id": "captcha" } } ], "databaseHooks": { "session": { "create": {} } }, "hooks": {} } } } ``` ### Which area(s) are affected? (Select all that apply) Backend, Client ### Auth config (if applicable) ```typescript stripe({ stripeClient, stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET!, createCustomerOnSignUp: false, subscription: { enabled: true, requireEmailVerification: false, plans: async () => { const plans = await prisma.activeStripePlans.findMany(); if (!plans) return []; return plans.map((plan) => ({ name: plan.name, priceId: plan.priceId, annualDiscountPriceId: plan.annualDiscountPriceId ?? undefined, limits: plan.limits as Record<string, number> | undefined, })); }, authorizeReference: async ({ user, session, referenceId, action }) => { // Check if the user has permission to manage subscriptions for this reference if ( action === "upgrade-subscription" || action === "cancel-subscription" || action === "restore-subscription" ) { const org = await prisma.member.findFirst({ where: { organizationId: referenceId, userId: user.id, }, }); return org?.role === "owner" || org?.role === "admin"; } return true; }, getCheckoutSessionParams: async ( { user, session, plan, subscription }, request, ) => { return { params: { allow_promotion_codes: true, }, }; }, }, }), ``` ### Additional context This is a scenario where the user cancels a plan and chooses another. When they think better and press "back," they are receiving an active plan without completing the purchase.
GiteaMirror added the bug label 2026-03-13 09:11:02 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 9, 2025):

This is a known bug in Better Auth's Stripe plugin: subscriptions can be marked as 'active' in your database even if payment isn't completed, especially when users cancel or switch plans during checkout. The root cause is that the plugin updated the subscription status without verifying payment with Stripe. This was fixed in PR #2930, which is not included in version 1.3.9. To resolve this, upgrade to a version that includes this PR or install the PR version directly.

Also, make sure your Stripe webhooks are correctly configured and being processed, as Better Auth relies on webhook events to keep subscription status in sync with Stripe. If webhooks fail, your local subscription data can become stale or incorrect, leading to issues like this one (details).

If you can't upgrade right away, you may need to manually clean up incorrect subscription records in your database to unblock affected users.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 9, 2025): <!-- Answer --> This is a known bug in Better Auth's Stripe plugin: subscriptions can be marked as 'active' in your database even if payment isn't completed, especially when users cancel or switch plans during checkout. The root cause is that the plugin updated the subscription status without verifying payment with Stripe. This was fixed in [PR #2930](https://github.com/better-auth/better-auth/pull/2930), which is not included in version 1.3.9. To resolve this, upgrade to a version that includes this PR or install the PR version directly. Also, make sure your Stripe webhooks are correctly configured and being processed, as Better Auth relies on webhook events to keep subscription status in sync with Stripe. If webhooks fail, your local subscription data can become stale or incorrect, leading to issues like this one [(details)](https://github.com/better-auth/better-auth/issues/3978). If you can't upgrade right away, you may need to manually clean up incorrect subscription records in your database to unblock affected users. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4545)
Author
Owner

@fabriziofeitosa commented on GitHub (Sep 9, 2025):

This is a known bug in Better Auth's Stripe plugin: subscriptions can be marked as 'active' in your database even if payment isn't completed, especially when users cancel or switch plans during checkout. The root cause is that the plugin updated the subscription status without verifying payment with Stripe. This was fixed in PR #2930, which is not included in version 1.3.9. To resolve this, upgrade to a version that includes this PR or install the PR version directly.

Also, make sure your Stripe webhooks are correctly configured and being processed, as Better Auth relies on webhook events to keep subscription status in sync with Stripe. If webhooks fail, your local subscription data can become stale or incorrect, leading to issues like this one (details).

If you can't upgrade right away, you may need to manually clean up incorrect subscription records in your database to unblock affected users.

To reply, just mention @dosu.

How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

I'm on the latest version, and this fix should be part of it.

@fabriziofeitosa commented on GitHub (Sep 9, 2025): > This is a known bug in Better Auth's Stripe plugin: subscriptions can be marked as 'active' in your database even if payment isn't completed, especially when users cancel or switch plans during checkout. The root cause is that the plugin updated the subscription status without verifying payment with Stripe. This was fixed in [PR #2930](https://github.com/better-auth/better-auth/pull/2930), which is not included in version 1.3.9. To resolve this, upgrade to a version that includes this PR or install the PR version directly. > > Also, make sure your Stripe webhooks are correctly configured and being processed, as Better Auth relies on webhook events to keep subscription status in sync with Stripe. If webhooks fail, your local subscription data can become stale or incorrect, leading to issues like this one [(details)](https://github.com/better-auth/better-auth/issues/3978). > > If you can't upgrade right away, you may need to manually clean up incorrect subscription records in your database to unblock affected users. > > _To reply, just mention [@dosu](https://go.dosu.dev/dosubot)._ > > How did I do? [Good](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/903a2660-ceaf-4355-8ad9-7c634d0c0a76?feedback_type=other)  [![Chat with Dosu](https://camo.githubusercontent.com/d9ffebb979729c9ef0fc4e3090dbae5b17cabbfec8afe378ada6b81913d6ad8a/68747470733a2f2f646f73752e6465762f646f73752d636861742d62616467652e737667)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github) [![Join Discord](https://camo.githubusercontent.com/d562c2df5e4567ea41d37f1d91a4da0839d8341037045b103b2da268998de17f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6a6f696e2d3538363546323f6c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465266c6162656c3d)](https://go.dosu.dev/discord-bot) [![Share on X](https://camo.githubusercontent.com/4649f705e2396d6f328dbc8e800a0509c9c17b3b20253b36706c393df124b93d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f582d73686172652d626c61636b)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4545) I'm on the latest version, and this fix should be part of it.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1891