signalapp/Signal-Server · error · SubscriptionInvalidArgumentsException
receipt credential request failed verification
Error message
receipt credential request failed verification
What it means
createReceiptCredentials throws SubscriptionInvalidArgumentsException("receipt credential request failed verification") when the zero-knowledge receipt issuance step (issueReceiptCredential or recordIssuance) raises VerificationFailedException. The request parsed fine but its cryptographic proof did not verify against the server's receipt credential public parameters/issuer key.
Solutions
- Regenerate the ReceiptCredentialRequest with the latest client library so it is built against the server's current receipt credential parameters.
- Confirm server zk ReceiptCredentialOperations issuer keys are unchanged/consistently configured; if keys were rotated, redeploy clients with the new public parameters.
- Check client and server use compatible versions of the receipts/zk library; upgrade whichever is stale.
Example fix
// before ReceiptCredentialRequest req = new ReceiptCredentialRequest(legacySerialized); // built with old params // after ReceiptCredentialRequest req = ReceiptCredentialRequestFactory.create(currentParams, receiptLevel, expiration);
Defensive patterns
Strategy: try-catch
Validate before calling
// client-side: ensure request built against the server's current public parameters
if (!paramsVersion.equals(SERVER_CURRENT_PARAMS_VERSION)) {
refreshReceiptParameters();
} Try / catch
try {
manager.createReceiptCredentials(creds, requestBytes);
} catch (SubscriptionInvalidArgumentsException e) {
// verification failed: rebuild request with current zk parameters and retry once
} catch (SubscriptionReceiptAlreadyRedeemedException e) {
// distinct failure: request already redeemed
} Prevention
- Ship receipt public parameters with the client and rotate them in lockstep with the server
- Pin zk receipt library versions across client and server
- Monitor VerificationFailedException spikes after server key rotations
When it happens
Trigger: Calling createReceiptCredentials where zkReceiptOperations.issueReceiptCredential rejects the ReceiptCredentialRequest proof, or recordIssuance fails verification, for a given subscription record and receipt level.
Common situations: Server rotated its ZK issuer key/parameters while the client built the request against old parameters; client and server zk library versions disagree on the proof format; a crafted/replayed request from a non-genuine client.
Related errors
- receipt credential presentation verification failed
- registration session is unverified
- recovery password could not be verified
- 429 Too Many Requests (rate limit exceeded)
- 403 Forbidden
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/816a612501e935ba.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/storage/SubscriptionManager.java:223
receiptCredentialRequest = new ReceiptCredentialRequest(receiptCredentialRequestBytes);
} catch (final InvalidInputException e) {
throw new SubscriptionInvalidArgumentsException("invalid receipt credential request", e);
}
final PaymentProvider processor = record.getProcessorCustomer().orElseThrow().processor();
final SubscriptionPaymentProcessor manager = getProcessor(processor);
final SubscriptionPaymentProcessor.ReceiptItem receipt = manager.getReceiptItem(record.subscriptionId);
final Instant expirationInstant = expiration.apply(receipt);
final ReceiptCredentialResponse receiptCredentialResponse;
try {
issuedReceiptsManager
.recordIssuance(receipt.itemId(), manager.getProvider(), receiptCredentialRequest, expirationInstant);
receiptCredentialResponse = zkReceiptOperations.issueReceiptCredential(
receiptCredentialRequest,
expirationInstant.getEpochSecond(),
receipt.level());
} catch (final VerificationFailedException e) {
throw new SubscriptionInvalidArgumentsException("receipt credential request failed verification", e);
} catch (final WriteConflictException _) {
throw new SubscriptionReceiptAlreadyRedeemedException();
}
return new ReceiptResult(receiptCredentialResponse, receipt, processor);
}
/**
* Add a payment method to a customer in a payment processor and update the table.
* <p>
* If the customer does not exist in the table, a customer is created via the subscriptionPaymentProcessor and added
* to the table. Not all payment processors support server-managed customers, so a payment processor that implements
* {@link CustomerAwareSubscriptionPaymentProcessor} must be passed in.
*
* @param subscriberCredentials Subscriber credentials derived from the subscriberId
* @param subscriptionPaymentProcessor A customer-aware payment processor to use. If the subscriber already has a
* payment processor, it must match the existing one.
* @param clientPlatform The platform of the client making the request
* @param paymentSetupFunction A function that takes the payment processor and the customer ID and beginsView on GitHub (pinned to 100ab61c82)