{"record":{"id":"cfd97c5cb5ba8d5b","repo":"signalapp/Signal-Server","slug":"senderrorresponse-requestmessage-response-status","errorCode":null,"errorMessage":"sendErrorResponse(requestMessage, Response.status(500).build());","messagePattern":"sendErrorResponse\\(requestMessage, Response\\.status\\(500\\)\\.build\\(\\)\\);","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProvider.java","lineNumber":238,"sourceCode":"        containerRequest, responseBody);\n\n    responseFuture\n        .thenAccept(response -> {\n          try {\n            final int responseBytes = responseBody.size();\n            containerRequest.setProperty(RESPONSE_LENGTH_PROPERTY, responseBytes);\n            sendResponse(requestMessage, response, responseBody);\n          } catch (IOException e) {\n            throw new RuntimeException(e);\n          }\n          requestLog.log(remoteAddress, containerRequest, response);\n        })\n        .exceptionally(exception -> {\n          logger.warn(\"Websocket Error: \" + requestMessage.getVerb() + \" \" + requestMessage.getPath() + \"\\n\"\n              + requestMessage.getBody(), exception);\n          try {\n            containerRequest.setProperty(RESPONSE_LENGTH_PROPERTY, 0);\n            sendErrorResponse(requestMessage, Response.status(500).build());\n          } catch (IOException e) {\n            logger.warn(\"Failed to send error response\", e);\n          }\n          requestLog.log(remoteAddress, containerRequest,\n              new ContainerResponse(containerRequest, Response.status(500).build()));\n          return null;\n        });\n  }\n\n  private static Map<String, List<String>> toLowerCaseHeaders(Map<String, List<String>> headers) {\n    return headers.entrySet().stream().collect(Collectors.toMap(\n        entry -> entry.getKey().trim().toLowerCase(),\n        Map.Entry::getValue));\n  }\n\n  @VisibleForTesting\n  static Map<String, List<String>> getCombinedHeaders(\n      final Map<String, List<String>> lowerCaseUpgradeRequestHeaders,","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/websocket-resources/src/main/java/org/whispersystems/websocket/WebSocketResourceProvider.java#L220-L256","documentation":"When a WebSocket request handled through the Jersey resource provider fails asynchronously, the provider logs the failure and sends a synthetic HTTP 500 response back over the WebSocket. This is a fallback path: the request itself threw, so the server can only report a generic internal error without details. The 500 is accompanied by a WARN log containing the exception that actually caused the failure.","triggerScenarios":"Any completion-stage exception raised while dispatching a WebSocket request through WebSocketResourceProvider.handleRequest — e.g. a Jersey/resource method throws an unhandled exception, serialization of the response fails, or an internal resource error occurs during onWebSocketBinary processing.","commonSituations":"Bugs in a WebSocket-exposed resource method (NPEs, DB failures), broken request bodies that blow up mid-processing, or downstream service exceptions not mapped by exception mappers, surfacing to the client as an opaque 500 over the socket.","solutions":["Inspect the server WARN log line 'Websocket Error: <verb> <path>' for the full stack trace of the root cause — the 500 itself carries no detail.","Fix the underlying exception thrown by the resource method handling that verb/path.","Register a javax.ws.rs.ext.ExceptionMapper for the exception type so it maps to a meaningful status instead of falling through to the 500 fallback.","Check the client sent a valid request body/verb/path matching a registered resource."],"exampleFix":"// before: resource method lets NPE propagate -> generic 500 over websocket\npublic Response handle(Request req) { return db.lookup(req.getId()).get(); }\n\n// after: map expected failure to a proper status\npublic Response handle(Request req) {\n  return db.lookup(req.getId())\n      .map(Response::ok)\n      .orElse(Response.status(404).build())\n      .build();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"client.onMessage((ws, bytes) -> {\n  try {\n    sendRequest(bytes);\n  } catch (Exception e) {\n    logger.warn(\"websocket request failed\", e); // server logs 'Websocket Error: ...' with the real cause\n  }\n});","preventionTips":["Register ExceptionMappers for all domain exceptions so failures map to meaningful statuses instead of the 500 fallback.","Monitor WARN logs for 'Websocket Error: verb path' to catch resource bugs early.","Validate request bodies/paths client-side before sending over the socket."],"tags":["websocket","http-500","internal-server-error"],"backgroundTag":"http-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"}