{"record":{"id":"804526b8d2f2a452","repo":"signalapp/Signal-Server","slug":"missing-required-response-attributes","errorCode":null,"errorMessage":"Missing required response attributes!","messagePattern":"Missing required response attributes!","errorType":"validation","errorClass":"InvalidMessageException","httpStatus":null,"severity":"error","filePath":"websocket-resources/src/main/java/org/whispersystems/websocket/messages/protobuf/ProtobufWebSocketMessage.java","lineNumber":29,"sourceCode":"import org.whispersystems.websocket.messages.WebSocketRequestMessage;\nimport org.whispersystems.websocket.messages.WebSocketResponseMessage;\nimport java.nio.ByteBuffer;\n\npublic class ProtobufWebSocketMessage implements WebSocketMessage {\n\n  private final SubProtocol.WebSocketMessage message;\n\n  ProtobufWebSocketMessage(ByteBuffer buffer) throws InvalidMessageException {\n    try {\n      this.message = SubProtocol.WebSocketMessage.parseFrom(ByteString.copyFrom(buffer));\n\n      if (getType() == Type.REQUEST_MESSAGE) {\n        if (!message.getRequest().hasVerb() || !message.getRequest().hasPath()) {\n          throw new InvalidMessageException(\"Missing required request attributes!\");\n        }\n      } else if (getType() == Type.RESPONSE_MESSAGE) {\n        if (!message.getResponse().hasId() || !message.getResponse().hasStatus() || !message.getResponse().hasMessage()) {\n          throw new InvalidMessageException(\"Missing required response attributes!\");\n        }\n      }\n    } catch (InvalidProtocolBufferException e) {\n      throw new InvalidMessageException(e);\n    }\n  }\n\n  ProtobufWebSocketMessage(SubProtocol.WebSocketMessage message) {\n    this.message = message;\n  }\n\n  @Override\n  public Type getType() {\n    if (message.getType().getNumber() == SubProtocol.WebSocketMessage.Type.REQUEST_VALUE &&\n        message.hasRequest())\n    {\n      return Type.REQUEST_MESSAGE;\n    } else if (message.getType().getNumber() == SubProtocol.WebSocketMessage.Type.RESPONSE_VALUE &&","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/websocket-resources/src/main/java/org/whispersystems/websocket/messages/protobuf/ProtobufWebSocketMessage.java#L11-L47","documentation":"For RESPONSE_MESSAGE frames, ProtobufWebSocketMessage requires the response to include id, status, and message fields. If any is missing the constructor throws InvalidMessageException with this message, because a response without these cannot be correlated or interpreted by the receiver.","triggerScenarios":"Building a SubProtocol.WebSocketMessage with type RESPONSE_MESSAGE but omitting response.id, response.status, or response.message before parsing it through the ProtobufWebSocketMessage constructor.","commonSituations":"Server-side code constructing responses manually and forgetting the message field; test fixtures with partial responses; protobuf field numbers changed across versions so fields land unset.","solutions":["Set response id, status, and message when building the WebSocketMessage response","Fix the code path that constructs the response to include all three attributes","Confirm client and server use the same SubProtocol protobuf schema"],"exampleFix":"// before\nResponse.newBuilder().setStatus(200).build()\n// after\nResponse.newBuilder().setId(requestId).setStatus(200).setMessage(\"OK\").build()","handlingStrategy":"validation","validationCode":"boolean isCompleteResponse(SubProtocol.WebSocketMessage msg) {\n    return msg.getType() == Type.RESPONSE_MESSAGE\n        && msg.getResponse().hasId() && msg.getResponse().hasStatus() && msg.getResponse().hasMessage();\n}","typeGuard":"boolean hasResponseAttributes(SubProtocol.WebSocketMessage msg) {\n    return msg.hasResponse() && msg.getResponse().hasId()\n        && msg.getResponse().hasStatus() && msg.getResponse().hasMessage();\n}","tryCatchPattern":"try { new ProtobufWebSocketMessage(buffer); } catch (InvalidMessageException e) { logger.warn(\"malformed response frame: {}\", e.getMessage()); }","preventionTips":["Build responses through a helper that always sets id/status/message","Echo the request id into the response","Version-lock the SubProtocol protobuf schema"],"tags":["websocket","protobuf","validation"],"backgroundTag":"schema-validation-failed","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"}