{"record":{"id":"975c26bcc503927e","repo":"toeverything/AFFiNE","slug":"subscription-already-exists","errorCode":"subscription_already_exists","errorMessage":"You have already subscribed to the ${plan} plan.","messagePattern":"You have already subscribed to the (.+?) plan\\.","errorType":"exception","errorClass":"SubscriptionAlreadyExists","httpStatus":400,"severity":"error","filePath":"packages/backend/server/src/plugins/payment/manager/user.ts","lineNumber":115,"sourceCode":"      lookupKey.variant !== null\n    ) {\n      throw new InvalidCheckoutParameters();\n    }\n\n    const active = await this.getVisibleSubscription({\n      plan: lookupKey.plan,\n      userId: user.id,\n    });\n    await this.assertNoActiveLocalEntitlement(user.id, lookupKey);\n    if (active?.provider === 'revenuecat') {\n      throw new ManagedByAppStoreOrPlay();\n    }\n\n    if (\n      active &&\n      !this.canCheckoutWithExistingSubscription(active.recurring, lookupKey)\n    ) {\n      throw new SubscriptionAlreadyExists({ plan: lookupKey.plan });\n    }\n\n    const customer = await this.getOrCreateCustomer(user.id);\n    const stripeSubscriptions = await this.stripe.subscriptions.list({\n      customer: customer.stripeCustomerId,\n      status: 'all',\n    });\n    this.assertNoActiveStripeSubscription(stripeSubscriptions.data, lookupKey);\n    await this.assertNoActiveRevenueCatSubscription(user.id, lookupKey);\n    const price = await this.getPrice(lookupKey);\n\n    if (!price || !(await this.isPriceAvailable(price))) {\n      throw new SubscriptionPlanNotFound({\n        plan: lookupKey.plan,\n        recurring: lookupKey.recurring,\n      });\n    }\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/packages/backend/server/src/plugins/payment/manager/user.ts#L97-L133","documentation":"checkout throws SubscriptionAlreadyExists when the user already holds an active subscription whose recurring interval cannot be combined with the requested plan, preventing duplicate or conflicting subscriptions.","triggerScenarios":"Thrown at packages/backend/server/src/plugins/payment/manager/user.ts:115 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["No action needed: the account already has an active subscription to this plan.","To change plans, cancel the current subscription first or use a plan-change flow.","Refresh the subscription state in the client to reflect the existing subscription."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}