signalapp/Signal-Server · error · BadRequestException
Operation cannot be performed with the
Error message
Operation cannot be performed with the ${processor} payment provider What it means
getCustomerAwareProcessor throws BadRequestException "Operation cannot be performed with the <processor> payment provider" when an operation that requires a customer-aware processor is invoked with GOOGLE_PLAY_BILLING or APPLE_APP_STORE, which have no direct customer/processor API in this service.
Solutions
- Use STRIPE or BRAINTREE as the processor for customer-aware operations
- Manage app-store subscriptions through the store's own APIs / the app-store-specific endpoints
- Validate the processor path parameter client-side before calling
Example fix
// before
PUT /v1/subscription/{subscriberId}/default_payment_method/GOOGLE_PLAY_BILLING/{token}
// after
PUT /v1/subscription/{subscriberId}/default_payment_method/STRIPE/{token} Defensive patterns
Strategy: validation
Validate before calling
const CUSTOMER_AWARE = ['STRIPE','BRAINTREE'];
if (!CUSTOMER_AWARE.includes(processor)) throw new Error(`${processor} has no customer-aware operations`); Type guard
const isCustomerAware = (p) => p === 'STRIPE' || p === 'BRAINTREE';
Prevention
- Only use STRIPE/BRAINTREE in processor path segments
- Handle app-store subscriptions through their store-specific flows
When it happens
Trigger: Any subscriber operation that routes through getCustomerAwareProcessor (e.g. default payment method, subscription level changes via processor path) with processor=GOOGLE_PLAY_BILLING or APPLE_APP_STORE in the URL.
Common situations: Clients constructing processor-segmented URLs for app-store subscriptions; automation iterating all PaymentProvider values against customer endpoints.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- cannot create payment methods with payment type
- The PAYPAL payment type must use…
- Invalid payment method
- cannot use play billing for one-time donations
- 400 Bad Request (INVALID_ARGUMENTS)
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/c58a3da1bf08ca3c.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java:355
final SubscriberCredentials subscriberCredentials =
SubscriberCredentials.process(authenticatedAccount, subscriberId, clock);
final Locale locale = getPayPalLocale(HeaderUtils.getAcceptableLanguagesForRequest(containerRequestContext));
final BraintreeManager.PayPalBillingAgreementApprovalDetails billingAgreementApprovalDetails = subscriptionManager.addPaymentMethodToCustomer(
subscriberCredentials,
braintreeManager,
getClientPlatform(userAgentString),
(mgr, _) -> mgr.createPayPalBillingAgreement(request.returnUrl, request.cancelUrl, locale.toLanguageTag()));
return new CreatePayPalBillingAgreementResponse(
billingAgreementApprovalDetails.approvalUrl(),
billingAgreementApprovalDetails.billingAgreementToken());
}
private CustomerAwareSubscriptionPaymentProcessor getCustomerAwareProcessor(PaymentProvider processor) {
return switch (processor) {
case STRIPE -> stripeManager;
case BRAINTREE -> braintreeManager;
case GOOGLE_PLAY_BILLING, APPLE_APP_STORE -> throw new BadRequestException("Operation cannot be performed with the " + processor + " payment provider");
};
}
@POST
@Path("/{subscriberId}/default_payment_method/{processor}/{paymentMethodToken}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ManagedAsync
public Response setDefaultPaymentMethodWithProcessor(
@Auth Optional<AuthenticatedDevice> authenticatedAccount,
@PathParam("subscriberId") String subscriberId,
@PathParam("processor") PaymentProvider processor,
@PathParam("paymentMethodToken") @NotEmpty String paymentMethodToken) throws SubscriptionException, IOException {
SubscriberCredentials subscriberCredentials =
SubscriberCredentials.process(authenticatedAccount, subscriberId, clock);
final CustomerAwareSubscriptionPaymentProcessor manager = getCustomerAwareProcessor(processor);
View on GitHub (pinned to 100ab61c82)