{"record":{"id":"4786ecb9e8b7f0da","repo":"signalapp/Signal-Server","slug":"invalid-payment-method","errorCode":null,"errorMessage":"Invalid payment method","messagePattern":"Invalid payment method","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java","lineNumber":292,"sourceCode":"      @Parameter(description=\"A base64-encoded donation permit retrieved from POST /v1/donation/permit\")\n      @HeaderParam(HeaderUtils.DONATION_PERMIT)\n      final Optional<DonationPermitHeader> donationPermitHeader,\n\n      @PathParam(\"subscriberId\") String subscriberId,\n      @QueryParam(\"type\") @DefaultValue(\"CARD\") PaymentMethod paymentMethodType,\n      @HeaderParam(HttpHeaders.USER_AGENT) @Nullable final String userAgentString) throws SubscriptionException {\n\n    SubscriberCredentials subscriberCredentials =\n        SubscriberCredentials.process(authenticatedAccount, subscriberId, clock);\n\n    final CustomerAwareSubscriptionPaymentProcessor customerAwareSubscriptionPaymentProcessor = switch (paymentMethodType) {\n      // Today, we always choose stripe to process non-paypal payment types, however we could use braintree to process\n      // other types (like CARD) in the future.\n      case CARD, SEPA_DEBIT, IDEAL -> stripeManager;\n      case GOOGLE_PLAY_BILLING, APPLE_APP_STORE ->\n          throw new BadRequestException(\"cannot create payment methods with payment type \" + paymentMethodType);\n      case PAYPAL -> throw new BadRequestException(\"The PAYPAL payment type must use create_payment_method/paypal\");\n      case UNKNOWN -> throw new BadRequestException(\"Invalid payment method\");\n    };\n\n    SubscriptionsUtil.recordDonationPermitPresent(donationPermitHeader.isPresent(), \"createPaymentMethod\", userAgentString);\n    final boolean spendSuccessful = donationPermitHeader.map(\n            permitHeader -> {\n              try {\n                return SubscriptionsUtil.verifyAndSpendDonationPermit(permitHeader.permit(), donationPermitsManager, clock);\n              } catch (VerificationFailedException e) {\n                return false;\n              }\n            })\n        .orElse(false);\n\n    if (!spendSuccessful) {\n      throw new WebApplicationException(Response.Status.UNAUTHORIZED);\n    }\n\n    final String token = subscriptionManager.addPaymentMethodToCustomer(","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java#L274-L310","documentation":"SubscriptionController.createPaymentMethod throws BadRequestException(\"Invalid payment method\") for the UNKNOWN payment type, i.e. the client sent a paymentMethodType that could not be resolved to a known enum member.","triggerScenarios":"POSTing create_payment_method with a paymentMethodType string that deserializes to PaymentMethodType.UNKNOWN (unrecognized/misspelled value or empty field).","commonSituations":"Typos in the payment type string; client SDK older than newly added enum values; serialization sending null/missing field that maps to UNKNOWN.","solutions":["Check the paymentMethodType string against the current enum values (CARD, SEPA_DEBIT, IDEAL, PAYPAL, GOOGLE_PLAY_BILLING, APPLE_APP_STORE)","Fix typos or casing in the request body","Update the client SDK if the server added payment types the client doesn't know"],"exampleFix":"// before\n{ \"paymentMethodType\": \"credit_card\" }\n// after\n{ \"paymentMethodType\": \"CARD\" }","handlingStrategy":"validation","validationCode":"const VALID = ['CARD','SEPA_DEBIT','IDEAL','PAYPAL','GOOGLE_PLAY_BILLING','APPLE_APP_STORE'];\nif (!VALID.includes(paymentMethodType)) throw new Error(`Unknown paymentMethodType: ${paymentMethodType}`);","typeGuard":"const isKnownPaymentType = (t) => ['CARD','SEPA_DEBIT','IDEAL','PAYPAL','GOOGLE_PLAY_BILLING','APPLE_APP_STORE'].includes(t);","tryCatchPattern":null,"preventionTips":["Validate payment type strings against the enum before sending","Keep the client's enum in sync with the server's PaymentMethodType","Never send undefined/null paymentMethodType"],"tags":["http-400","bad-request","enum","payments"],"backgroundTag":"invalid-enum-value","analyzedSha":"100ab61c82627582c867d19e1c0561ba2781e927","analyzedAt":"2026-09-09T13:29:47.883Z","contentChangedAt":"2026-09-09T13:29:47.883Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}