{"record":{"id":"c63027df5e90396b","repo":"hcengineering/platform","slug":"failed-to-uncancel-subscription-at-provider","errorCode":null,"errorMessage":"Failed to uncancel subscription at provider","messagePattern":"Failed to uncancel subscription at provider","errorType":"http","errorClass":null,"httpStatus":500,"severity":"critical","filePath":"services/payment/pod-payment/src/server.ts","lineNumber":349,"sourceCode":"        async (ctx) => {\n          const subscriptionId = req.params.subscriptionId\n\n          // Get subscription from our database using internal ID\n          const subscription = await accountClient.getSubscriptionById(subscriptionId)\n\n          if (subscription === undefined || subscription === null) {\n            res.status(404).json({ error: 'Subscription not found' })\n            return\n          }\n\n          let uncanceledSubscription: SubscriptionData | null\n\n          try {\n            // Uncancel via provider using the provider's subscription ID\n            uncanceledSubscription = await provider.uncancelSubscription(ctx, subscription.providerSubscriptionId)\n          } catch (err) {\n            ctx.error('Failed to uncancel subscription at provider', { err })\n            res.status(500).json({ error: 'Failed to uncancel subscription at provider' })\n            return\n          }\n\n          if (uncanceledSubscription === null) {\n            res.status(404).json({ error: 'Failed to uncancel subscription at provider' })\n            return\n          }\n\n          // Upsert the updated subscription into our database\n          await accountClient.upsertSubscription(uncanceledSubscription)\n\n          res.status(200).json(uncanceledSubscription)\n        },\n        req,\n        res,\n        () => {}\n      )\n    }","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/payment/pod-payment/src/server.ts#L331-L367","documentation":"This 500 is returned when provider.uncancelSubscription(...) throws while asking the external payment provider to re-activate a canceled subscription. The raw error is logged via ctx.error and a generic message is returned to the client. Common underlying causes are provider API errors, invalid credentials, or the provider refusing reactivation of that subscription.","triggerScenarios":"POST /api/v1/subscriptions/:subscriptionId/uncancel where the local record exists but provider.uncancelSubscription throws — provider-side subscription already fully terminated (cannot be revived), unknown providerSubscriptionId, expired/invalid provider API keys, provider outage, or network timeout.","commonSituations":"Trying to uncancel after the provider has completed the cancellation at period end (no longer revivable); provider account/key mismatch; provider incident; subscription migrated between provider accounts so the stored ID no longer resolves.","solutions":["Read the server logs (ctx.error 'Failed to uncancel subscription at provider') for the provider's concrete error.","Check the provider dashboard: if the subscription is fully terminated, create a new subscription instead of un-canceling.","Verify provider credentials match the account that owns providerSubscriptionId.","Retry with backoff for transient provider/network errors.","If the provider says the subscription cannot be revived, re-subscribe the workspace and update the local record."],"exampleFix":"// before\nawait provider.uncancelSubscription(ctx, sub.providerSubscriptionId) // throws: cancellation already finalized\n\n// after\ntry {\n  await provider.uncancelSubscription(ctx, sub.providerSubscriptionId)\n} catch (reviveErr) {\n  // fall back to a fresh checkout\n  await provider.createSubscription(ctx, request, workspaceUuid, workspaceUrl, accountUuid)\n}","handlingStrategy":"fallback","validationCode":"const remote = await provider.getSubscription(ctx, sub.providerSubscriptionId)\nif (remote !== null && remote.status === 'active') {\n  // already active; skip uncancel entirely\n}\nif (remote === null) {\n  // cannot revive; plan a fresh createSubscription flow instead\n}","typeGuard":"function isRevivable(s: SubscriptionData | null): boolean {\n  return s !== null && (s.status === 'canceled' || s.status === 'canceling')\n}","tryCatchPattern":"try {\n  await uncancelSubscription(id)\n} catch (e) {\n  // fall back: create a new subscription via checkout instead of failing the user\n  await startFreshCheckout(workspaceUuid)\n}","preventionTips":["Only offer 'uncancel' while the cancellation is still pending at the provider (before period end).","Verify subscription status remotely before attempting reactivation.","Provide a re-subscribe fallback path in the product for non-revivable subscriptions.","Retry only transient provider errors; treat permanent provider refusals as 're-subscribe'."],"tags":["http-500","payment-provider","external-api","network"],"backgroundTag":"payment-provider-request-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}