{"record":{"id":"6f31b3677fb23070","repo":"signalapp/Signal-Server","slug":"return-response-status-508-build","errorCode":null,"errorMessage":"return Response.status(508).build();","messagePattern":"return Response\\.status\\(508\\)\\.build\\(\\);","errorType":"http","errorClass":"ServerRejectedException","httpStatus":508,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/mappers/ServerRejectedExceptionMapper.java","lineNumber":16,"sourceCode":"/*\n * Copyright 2021 Signal Messenger, LLC\n * SPDX-License-Identifier: AGPL-3.0-only\n */\n\npackage org.whispersystems.textsecuregcm.mappers;\n\nimport jakarta.ws.rs.core.Response;\nimport jakarta.ws.rs.ext.ExceptionMapper;\nimport org.whispersystems.textsecuregcm.controllers.ServerRejectedException;\n\npublic class ServerRejectedExceptionMapper implements ExceptionMapper<ServerRejectedException> {\n\n  @Override\n  public Response toResponse(final ServerRejectedException exception) {\n    return Response.status(508).build();\n  }\n}\n","sourceCodeStart":1,"sourceCodeEnd":19,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/mappers/ServerRejectedExceptionMapper.java#L1-L19","documentation":"The ServerRejectedExceptionMapper maps ServerRejectedException to HTTP 508 Loop Detected. It is returned when the registration service's fraud/abuse detection (or an upstream checker) flatly rejects the operation for this account/session — a deliberate server-side rejection rather than a rate limit or validation error. The body is empty.","triggerScenarios":"Calling registration/verification endpoints (or anything that throws ServerRejectedException) where an anti-abuse backend signals a hard rejection of the request for the given number/session.","commonSituations":"Numbers or IPs on fraud blocklists; VoIP/virtual numbers flagged by abuse scoring; clients hammering verification flows until the fraud system hard-rejects them.","solutions":["Stop retrying — 508 is a deliberate rejection, and retries can worsen the flag","Try from a different network/IP and a legitimate (non-VoIP) number if wrongly flagged","Appeal via the service's support channels if the rejection is in error","Review server-side abuse-check configuration if rejections are over-broad"],"exampleFix":"// before\nwhile (!success) { requestVerification(number); } // retries into hard rejection\n// after\nif (response.code() == 508) {\n  abortFlow(\"server rejected this number/session — do not retry\");\n}","handlingStrategy":"fallback","validationCode":"// screen obviously flag-prone inputs before calling\nif (phoneNumberUtil.getNumberType(number) == PhoneNumberType.VOIP && !allowVoip) {\n  warnUser(\"this number type is commonly rejected\");\n}","typeGuard":null,"tryCatchPattern":"if (response.code() == 508) {\n  abortFlow(\"server rejected this operation; do not retry\");\n  offerSupportAppeal();\n}","preventionTips":["Never retry 508 responses — it is a hard rejection","Use legitimate non-VoIP numbers and stable IPs for verification flows","Throttle verification attempts well before fraud thresholds","Provide a support/appeal path for false-positive rejections"],"tags":["http","fraud-detection","registration","rejection"],"backgroundTag":"api-error-response","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"}