signalapp/Signal-Server · error · InvalidMessageException
Missing required response attributes!
Error message
Missing required response attributes!
What it means
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.
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
Example fix
// before
Response.newBuilder().setStatus(200).build()
// after
Response.newBuilder().setId(requestId).setStatus(200).setMessage("OK").build() Defensive patterns
Strategy: validation
Validate before calling
boolean isCompleteResponse(SubProtocol.WebSocketMessage msg) {
return msg.getType() == Type.RESPONSE_MESSAGE
&& msg.getResponse().hasId() && msg.getResponse().hasStatus() && msg.getResponse().hasMessage();
} Type guard
boolean hasResponseAttributes(SubProtocol.WebSocketMessage msg) {
return msg.hasResponse() && msg.getResponse().hasId()
&& msg.getResponse().hasStatus() && msg.getResponse().hasMessage();
} Try / catch
try { new ProtobufWebSocketMessage(buffer); } catch (InvalidMessageException e) { logger.warn("malformed response frame: {}", e.getMessage()); } Prevention
- Build responses through a helper that always sets id/status/message
- Echo the request id into the response
- Version-lock the SubProtocol protobuf schema
When it happens
Trigger: Building a SubProtocol.WebSocketMessage with type RESPONSE_MESSAGE but omitting response.id, response.status, or response.message before parsing it through the ProtobufWebSocketMessage constructor.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Missing required request attributes!
- string expected to be non-empty
- repeated field is expected to be non-empty
- message expected to be present
- Received bad envelope type
AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09).
Data as JSON: /api/errors/804526b8d2f2a452.
Report an issue: GitHub.
Appendix: source
Thrown at websocket-resources/src/main/java/org/whispersystems/websocket/messages/protobuf/ProtobufWebSocketMessage.java:29
import org.whispersystems.websocket.messages.WebSocketRequestMessage;
import org.whispersystems.websocket.messages.WebSocketResponseMessage;
import java.nio.ByteBuffer;
public class ProtobufWebSocketMessage implements WebSocketMessage {
private final SubProtocol.WebSocketMessage message;
ProtobufWebSocketMessage(ByteBuffer buffer) throws InvalidMessageException {
try {
this.message = SubProtocol.WebSocketMessage.parseFrom(ByteString.copyFrom(buffer));
if (getType() == Type.REQUEST_MESSAGE) {
if (!message.getRequest().hasVerb() || !message.getRequest().hasPath()) {
throw new InvalidMessageException("Missing required request attributes!");
}
} else if (getType() == Type.RESPONSE_MESSAGE) {
if (!message.getResponse().hasId() || !message.getResponse().hasStatus() || !message.getResponse().hasMessage()) {
throw new InvalidMessageException("Missing required response attributes!");
}
}
} catch (InvalidProtocolBufferException e) {
throw new InvalidMessageException(e);
}
}
ProtobufWebSocketMessage(SubProtocol.WebSocketMessage message) {
this.message = message;
}
@Override
public Type getType() {
if (message.getType().getNumber() == SubProtocol.WebSocketMessage.Type.REQUEST_VALUE &&
message.hasRequest())
{
return Type.REQUEST_MESSAGE;
} else if (message.getType().getNumber() == SubProtocol.WebSocketMessage.Type.RESPONSE_VALUE &&View on GitHub (pinned to 100ab61c82)