{"record":{"id":"f670764555148cf4","repo":"calcom/cal.diy","slug":"btcpay-server-does-not-support-automatic-refunds-f","errorCode":null,"errorMessage":"BTCPay Server does not support automatic refunds for Bitcoin payments","messagePattern":"BTCPay Server does not support automatic refunds for Bitcoin payments","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/app-store/btcpayserver/lib/PaymentService.ts","lineNumber":158,"sourceCode":"              isPaid: false,\r\n              attendee: { name: bookerName, email: bookerEmail },\r\n            },\r\n          }\r\n        ),\r\n      });\r\n      if (!paymentData) throw new Error(\"Failed to store Payment data\");\r\n      return paymentData;\r\n    } catch (error) {\r\n      log.error(\"BTCPay server: Payment could not be created\", bookingId, safeStringify(error));\r\n      throw new Error(ErrorCode.PaymentCreationFailure);\r\n    }\r\n  }\r\n\r\n  async update(): Promise<Payment> {\r\n    throw new Error(\"Method not implemented.\");\r\n  }\r\n  async refund(): Promise<Payment> {\r\n    throw new Error(\"BTCPay Server does not support automatic refunds for Bitcoin payments\");\r\n  }\r\n\r\n  async collectCard(\r\n    _payment: Pick<Prisma.PaymentUncheckedCreateInput, \"amount\" | \"currency\">,\r\n    _bookingId: number,\r\n    _bookerEmail: string,\r\n    _paymentOption: PaymentOption\r\n  ): Promise<Payment> {\r\n    throw new Error(\"Method not implemented\");\r\n  }\r\n\r\n  chargeCard(\r\n    _payment: Pick<Prisma.PaymentUncheckedCreateInput, \"amount\" | \"currency\">,\r\n    _bookingId: number\r\n  ): Promise<Payment> {\r\n    throw new Error(\"Method not implemented.\");\r\n  }\r\n\r","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/calcom/cal.diy/blob/176037d0afbe572f870a3c702985e7cd83fe6c0c/packages/app-store/btcpayserver/lib/PaymentService.ts#L140-L176","documentation":"`PaymentService.refund()` is intentionally not implemented for BTCPay and always throws this Error. Bitcoin payments cannot be automatically reversed through BTCPay Server's API, so the contract method is a deliberate no-op that signals unsupported behavior rather than silently failing.","triggerScenarios":"Any code path that calls `.refund()` on the BTCPay payment adapter — e.g. a booking cancellation flow that automatically refunds payments, or a generic refund API endpoint that doesn't filter by payment method capability.","commonSituations":"A cancellation/refund workflow added without checking each payment app's refund support; a generic admin tool iterating over payment adapters and invoking refund uniformly; UI button that doesn't hide for Bitcoin payments.","solutions":["Before calling `refund()`, check the payment app's capability flag (or `instanceof`/slug check) and skip/branch for BTCPay.","Surface a user-facing message that BTCPay/Bitcoin refunds must be handled manually on-chain.","In a generic refund dispatcher, catch this Error and mark the refund as `manual_action_required` rather than failing the workflow.","Add a `supportsRefund` capability on the payment adapter interface so callers can detect this without try/catch."],"exampleFix":"// before\nawait paymentService.refund();\n\n// after\nif (paymentService.appSlug === \"btcpayserver\") {\n  await markRefundRequiresManualAction(paymentId);\n} else {\n  await paymentService.refund();\n}","handlingStrategy":"type-guard","validationCode":"const supportsRefund = (slug: string) => slug !== \"btcpayserver\";\nif (!supportsRefund(paymentAppSlug)) {\n  await markRefundRequiresManualAction(paymentId);\n  return;\n}","typeGuard":"function supportsAutoRefund(appSlug: string): boolean {\n  return appSlug !== \"btcpayserver\";\n}","tryCatchPattern":"try {\n  await paymentService.refund();\n} catch (e) {\n  if (e instanceof Error && /does not support automatic refunds/.test(e.message)) {\n    await markRefundRequiresManualAction(paymentId);\n    return;\n  }\n  throw e;\n}","preventionTips":["Add a `supportsRefund` capability to the payment adapter interface.","Branch refund workflows on adapter capability before calling refund().","Hide auto-refund UI for BTCPay/Bitcoin payments.","Document manual refund steps for Bitcoin payments in ops runbooks."],"tags":["payment","refund","unsupported","btcpay","by-design"],"backgroundTag":null,"analyzedSha":"176037d0afbe572f870a3c702985e7cd83fe6c0c","analyzedAt":"2026-08-12T19:12:41.464Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}