{"record":{"id":"ede606dc52f4bc52","repo":"signalapp/Signal-Server","slug":"string-expected-to-be-non-empty","errorCode":null,"errorMessage":"string expected to be non-empty","messagePattern":"string expected to be non-empty","errorType":"validation","errorClass":"FieldValidationException","httpStatus":null,"severity":"error","filePath":"service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/NonEmptyFieldValidator.java","lineNumber":45,"sourceCode":"\n  @Override\n  protected void validateBytesValue(\n      final Boolean extensionValue,\n      final ByteString fieldValue) throws FieldValidationException {\n    if (!fieldValue.isEmpty()) {\n      return;\n    }\n    throw new FieldValidationException(\"byte array expected to be non-empty\");\n  }\n\n  @Override\n  protected void validateStringValue(\n      final Boolean extensionValue,\n      final String fieldValue) throws FieldValidationException {\n    if (StringUtils.isNotEmpty(fieldValue)) {\n      return;\n    }\n    throw new FieldValidationException(\"string expected to be non-empty\");\n  }\n\n  @Override\n  protected void validateRepeatedField(\n      final Boolean extensionValue,\n      final Descriptors.FieldDescriptor fd,\n      final List<?> repeated) throws FieldValidationException {\n    if (repeated.size() > 0) {\n      return;\n    }\n    throw new FieldValidationException(\"repeated field is expected to be non-empty\");\n  }\n}\n","sourceCodeStart":27,"sourceCodeEnd":59,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/NonEmptyFieldValidator.java#L27-L59","documentation":"NonEmptyFieldValidator.validateStringValue throws FieldValidationException when a proto field annotated as required-non-empty is null or empty (StringUtils.isNotEmpty fails). The Signal gRPC layer runs these validators on incoming requests so malformed/empty required fields are rejected at the boundary.","triggerScenarios":"Calling a Signal gRPC endpoint with a request whose non-empty-string field is null, \"\" or (per StringUtils.isNotEmpty) not set; e.g. an empty account identifier, device name, or message field.","commonSituations":"Clients constructing protobuf requests with default/omitted string fields; partial migrations where a previously optional field became required; test clients sending empty placeholders.","solutions":["Set the field to a non-empty string before sending the request","On the client, skip sending the request if the value is null/blank and surface a user-facing error","Check the proto annotations to confirm which fields are marked non-empty and ensure all are populated"],"exampleFix":"// before\nAccountIdentifierRequest.newBuilder().setAcifield(\"\").build();\n// after\nif (aci != null && !aci.isBlank()) {\n  req = AccountIdentifierRequest.newBuilder().setAcifield(aci).build();\n}","handlingStrategy":"validation","validationCode":"if (value == null || value.isBlank()) throw new IllegalArgumentException(\"field must be a non-empty string\");","typeGuard":"boolean isNonEmpty(String s) { return s != null && !s.isBlank(); }","tryCatchPattern":"try { stub.call(request); } catch (StatusRuntimeException e) { if (e.getStatus().getCode() == Status.Code.INVALID_ARGUMENT) { /* handle empty field */ } }","preventionTips":["Null/blank-check every required string before building protobuf requests","Treat proto3 unset strings as empty and validate accordingly","Add client-side unit tests covering empty-field rejection"],"tags":["grpc","validation","protobuf"],"backgroundTag":"empty-required-field","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"}