{"record":{"id":"da1077b98089a808","repo":"signalapp/Signal-Server","slug":"message-expected-to-be-present","errorCode":null,"errorMessage":"message expected to be present","messagePattern":"message expected to be present","errorType":"validation","errorClass":"FieldValidationException","httpStatus":null,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/PresentFieldValidator.java","lineNumber":29,"sourceCode":"\npublic class PresentFieldValidator extends FieldValidator<Boolean> {\n\n  public PresentFieldValidator() {\n    super(\"present\",\n        Set.of(Descriptors.FieldDescriptor.Type.MESSAGE),\n        MissingOptionalAction.FAIL,\n        true);\n  }\n\n  @Override\n  protected Boolean resolveExtensionValue(final Object extensionValue) throws FieldValidationException {\n    return requireFlagExtension(extensionValue);\n  }\n\n  @Override\n  protected void validateMessageValue(final Boolean extensionValue, final Message msg) throws FieldValidationException {\n    if (msg == null) {\n      throw new FieldValidationException(\"message expected to be present\");\n    }\n  }\n}\n","sourceCodeStart":11,"sourceCodeEnd":33,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/PresentFieldValidator.java#L11-L33","documentation":"PresentFieldValidator.validateMessageValue throws FieldValidationException when a proto message field annotated as required-present is null. Signal's gRPC layer uses this to reject requests missing an embedded message sub-field.","triggerScenarios":"Calling a Signal gRPC endpoint without setting a required nested message field (e.g. missing ServiceIdentifier, missing DeviceSpecifier), so the validator receives a null Message.","commonSituations":"Clients forgetting to set a nested message builder; proto3 code assuming unset message fields default to an instance rather than null; copy-pasted request builders missing one sub-message.","solutions":["Set the required message field via its setter (e.g. .setServiceIdentifier(...)) before building the request","Client-side null-check nested messages before sending","Compare against the proto definition to enumerate which message fields are annotated as required"],"exampleFix":"// before\nRequest.newBuilder().build(); // nested message never set\n// after\nRequest.newBuilder()\n    .setServiceIdentifier(ServiceId.newBuilder().setAci(aciUuid).build())\n    .build();","handlingStrategy":"validation","validationCode":"if (request.getServiceIdentifier() == null) throw new IllegalArgumentException(\"service identifier message is required\");","typeGuard":"boolean hasMessage(Request r) { return r.hasServiceIdentifier(); }","tryCatchPattern":"try { stub.call(request); } catch (StatusRuntimeException e) { if (e.getStatus().getCode() == Status.Code.INVALID_ARGUMENT) { /* handle missing message field */ } }","preventionTips":["Use hasXxx() checks on proto message fields before sending","Build nested messages in dedicated factory methods so they are never omitted","Review proto annotations listing required-present fields"],"tags":["grpc","validation","protobuf"],"backgroundTag":"missing-required-argument","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"}