{"record":{"id":"e3beb74bc6488c52","repo":"signalapp/Signal-Server","slug":"invalid-create-call-link-credential-request","errorCode":null,"errorMessage":"Invalid create call link credential request","messagePattern":"Invalid create call link credential request","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallLinkController.java","lineNumber":73,"sourceCode":"  @ApiResponse(responseCode = \"401\", description = \"Account authentication check failed.\")\n  @ApiResponse(responseCode = \"422\", description = \"Invalid request format.\")\n  @ApiResponse(responseCode = \"429\", description = \"Ratelimited.\")\n  public CreateCallLinkCredential getCreateAuth(\n      final @Auth AuthenticatedDevice auth,\n      final @NotNull @Valid GetCreateCallLinkCredentialsRequest request,\n      @Parameter(description = \"Whether to use libsignal v0.101.0+ secret params\")\n      final @QueryParam(\"v101\") boolean v101\n  ) throws RateLimitExceededException {\n\n    rateLimiters.getCreateCallLinkLimiter().validate(auth.accountIdentifier());\n\n    final Instant truncatedDayTimestamp = Instant.now().truncatedTo(ChronoUnit.DAYS);\n\n    CreateCallLinkCredentialRequest createCallLinkCredentialRequest;\n    try {\n      createCallLinkCredentialRequest = new CreateCallLinkCredentialRequest(request.createCallLinkCredentialRequest());\n    } catch (InvalidInputException e) {\n      throw new BadRequestException(\"Invalid create call link credential request\", e);\n    }\n\n    return new CreateCallLinkCredential(\n        createCallLinkCredentialRequest.issueCredential(new ServiceId.Aci(auth.accountIdentifier()), truncatedDayTimestamp, v101 ? genericServerSecretParams : genericServerSecretParamsPreV101).serialize(),\n        truncatedDayTimestamp.getEpochSecond()\n    );\n  }\n}\n","sourceCodeStart":55,"sourceCodeEnd":82,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallLinkController.java#L55-L82","documentation":"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'.","triggerScenarios":"POST to /v1/call-link/auth with a request body whose createCallLinkCredentialRequest field holds malformed or invalid byte content.","commonSituations":"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).","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)"],"exampleFix":"// before\nrequest.createCallLinkCredentialRequest = someBase64String.getBytes();\n// after\nbyte[] bytes = CreateCallLinkCredentialRequestJsonAdapter\n    .serialize(new CreateCallLinkCredentialRequest(randomToken));\nrequest.createCallLinkCredentialRequest = bytes;","handlingStrategy":"try-catch","validationCode":"try { new CreateCallLinkCredentialRequest(bytes); } catch (InvalidInputException e) { rebuildCredentialRequest(); }","typeGuard":null,"tryCatchPattern":"try { callLinkAuth(request); } catch (WebApplicationException e) { if (e.getResponse().getStatus() == 400) regenerateCredentialRequestAndRetry(); }","preventionTips":["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"],"tags":["http-400","call-links","validation","serialization"],"backgroundTag":"invalid-argument-format","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"}