signalapp/Signal-Server · error · BadRequestException
Invalid create call link credential request
Error message
Invalid create call link credential request
What it means
CallLinkController.getCreateAuth wraps the client-supplied create-call-link-credential-request bytes into CreateCallLinkCredentialRequest; if parsing raises InvalidInputException the endpoint returns 400 'Invalid create call link credential request'.
Solutions
- Regenerate the CreateCallLinkCredentialRequest client-side with a current, matching library version
- Ensure the raw serialized bytes (correct encoding) are placed in the request field unmodified
- Verify client and server use compatible GenericServerSecretParams / version (v101 flag)
Example fix
// before
request.createCallLinkCredentialRequest = someBase64String.getBytes();
// after
byte[] bytes = CreateCallLinkCredentialRequestJsonAdapter
.serialize(new CreateCallLinkCredentialRequest(randomToken));
request.createCallLinkCredentialRequest = bytes; Defensive patterns
Strategy: try-catch
Validate before calling
try { new CreateCallLinkCredentialRequest(bytes); } catch (InvalidInputException e) { rebuildCredentialRequest(); } Try / catch
try { callLinkAuth(request); } catch (WebApplicationException e) { if (e.getResponse().getStatus() == 400) regenerateCredentialRequestAndRetry(); } Prevention
- Round-trip validate serialized credential bytes before sending
- Keep client crypto libs updated in lockstep with server
- Use raw bytes, not base64 strings, in the request field
When it happens
Trigger: POST to /v1/call-link/auth with a request body whose createCallLinkCredentialRequest field holds malformed or invalid byte content.
Common situations: Client built the credential request with the wrong library version or wrong server secret params; protobuf bytes corrupted/truncated in transit or mis-serialized (e.g. base64 vs raw mixup).
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid length
- invalid receipt credential request
- Illegal timestamp
- Recipient list is empty
- Multi-recipient message contains duplicate recipient
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/e3beb74bc6488c52.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallLinkController.java:73
@ApiResponse(responseCode = "401", description = "Account authentication check failed.")
@ApiResponse(responseCode = "422", description = "Invalid request format.")
@ApiResponse(responseCode = "429", description = "Ratelimited.")
public CreateCallLinkCredential getCreateAuth(
final @Auth AuthenticatedDevice auth,
final @NotNull @Valid GetCreateCallLinkCredentialsRequest request,
@Parameter(description = "Whether to use libsignal v0.101.0+ secret params")
final @QueryParam("v101") boolean v101
) throws RateLimitExceededException {
rateLimiters.getCreateCallLinkLimiter().validate(auth.accountIdentifier());
final Instant truncatedDayTimestamp = Instant.now().truncatedTo(ChronoUnit.DAYS);
CreateCallLinkCredentialRequest createCallLinkCredentialRequest;
try {
createCallLinkCredentialRequest = new CreateCallLinkCredentialRequest(request.createCallLinkCredentialRequest());
} catch (InvalidInputException e) {
throw new BadRequestException("Invalid create call link credential request", e);
}
return new CreateCallLinkCredential(
createCallLinkCredentialRequest.issueCredential(new ServiceId.Aci(auth.accountIdentifier()), truncatedDayTimestamp, v101 ? genericServerSecretParams : genericServerSecretParamsPreV101).serialize(),
truncatedDayTimestamp.getEpochSecond()
);
}
}
View on GitHub (pinned to 100ab61c82)