signalapp/Signal-Server · error · ForbiddenException
must not use authenticated connection for call quality…
Error message
must not use authenticated connection for call quality survey submissions
What it means
CallQualitySurveyController.submitCallQualitySurvey is designed for anonymous submissions only. If the request contains an authenticated device (session/basic auth), the controller throws ForbiddenException (HTTP 403) to guarantee survey submissions cannot be linked to an account.
Solutions
- Submit the survey from a connection without any account credentials
- Use a separate anonymous HTTP client for survey endpoints
- Verify no auth cookies/headers are auto-attached by the transport layer
Example fix
// before
accountClient.post("/v1/call_quality/...", surveyBytes);
// after
newAnonymousClient().post("/v1/call_quality/...", surveyBytes); Defensive patterns
Strategy: validation
Validate before calling
if (client.hasStoredCredentials()) throw new IllegalStateException("survey submission must be anonymous"); Try / catch
try { submitSurvey(bytes); } catch (ForbiddenException e) { switchToAnonymousClientAndResubmit(); } Prevention
- Dedicate an anonymous transport for survey uploads
- Log out / clear auth headers before survey submission
- Privacy: never send surveys over authenticated sessions
When it happens
Trigger: POST to the call quality survey endpoint while logged in over the same connection — authenticatedDevice is present.
Common situations: In-app clients reusing the main account's authenticated HTTP client for the survey upload; proxies injecting credentials.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- must not use authenticated connection for login purchase…
- Operation requires unauthenticated access
- recovery password could not be verified
- must not use authenticated connection for anonymous…
- Invalid protobuf entity
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/841473677d535cf8.
Report an issue: GitHub.
Appendix: source
Thrown at service/src/main/java/org/whispersystems/textsecuregcm/controllers/CallQualitySurveyController.java:62
@PUT
@Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Submit survey response", description = "Submits a call quality survey response")
@ApiResponse(responseCode = "204", description = "The survey response was submitted successfully")
@ApiResponse(responseCode = "422", description = "The survey response could not be parsed")
@ApiResponse(responseCode = "429", description = "Too many attempts", headers = @Header(
name = "Retry-After",
description = "If present, an positive integer indicating the number of seconds before a subsequent attempt could succeed"))
@RateLimitedByIp(RateLimiters.For.SUBMIT_CALL_QUALITY_SURVEY)
public void submitCallQualitySurvey(@Auth final Optional<AuthenticatedDevice> authenticatedDevice,
@RequestBody(description = "A serialized survey response protobuf entity")
@NotNull final byte[] surveyResponse,
@HeaderParam(HttpHeaders.USER_AGENT) final String userAgentString,
@Context final ContainerRequestContext requestContext) {
if (authenticatedDevice.isPresent()) {
throw new ForbiddenException("must not use authenticated connection for call quality survey submissions");
}
final SubmitCallQualitySurveyRequest submitCallQualitySurveyRequest;
try {
submitCallQualitySurveyRequest = SubmitCallQualitySurveyRequest.parseFrom(surveyResponse);
} catch (final InvalidProtocolBufferException e) {
throw new WebApplicationException("Invalid protobuf entity", 422);
}
final String remoteAddress = (String) requestContext.getProperty(RemoteAddressFilter.REMOTE_ADDRESS_ATTRIBUTE_NAME);
try {
callQualitySurveyManager.submitCallQualitySurvey(submitCallQualitySurveyRequest, remoteAddress, userAgentString);
} catch (final CallQualityInvalidArgumentsException e) {
throw new WebApplicationException(e.getMessage(), 422);
}
}View on GitHub (pinned to 100ab61c82)