{"record":{"id":"6f86a78856890b96","repo":"signalapp/Signal-Server","slug":"byte-array-expected-to-be-non-empty","errorCode":null,"errorMessage":"byte array expected to be non-empty","messagePattern":"byte array 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":35,"sourceCode":"    super(\"nonEmpty\", Set.of(\n        Descriptors.FieldDescriptor.Type.STRING,\n        Descriptors.FieldDescriptor.Type.BYTES\n    ), MissingOptionalAction.FAIL, 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 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) {","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/signalapp/Signal-Server/blob/100ab61c82627582c867d19e1c0561ba2781e927/service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/NonEmptyFieldValidator.java#L17-L53","documentation":"NonEmptyFieldValidator.validateBytesValue rejects empty ByteString fields. If the bytes field is empty, it throws FieldValidationException('byte array expected to be non-empty'), enforcing that required binary fields carry data.","triggerScenarios":"gRPC requests where a bytes field (e.g. profile key, backup key, storage manifest) is present but zero-length — typically because the client passed a new byte[0] or an unset/empty value.","commonSituations":"Client code generating keys before they are ready (no key material available yet); failing to check a byte array before encoding; proto fields defaulting to empty bytes when not explicitly set.","solutions":["Ensure the byte array is generated/loaded (non-zero length) before placing it in the request","Check client-side: if the field is genuinely optional, don't set the field at all rather than setting empty bytes","Verify the key-generation step didn't fail silently and return an empty array","Log/inspect the value on the client to confirm non-empty content before sending"],"exampleFix":"// before\nbyte[] backupKey = new byte[0];\nrequest.setBackupKey(ByteString.copyFrom(backupKey));\n// after\nif (backupKey.length > 0) {\n  request.setBackupKey(ByteString.copyFrom(backupKey));\n}","handlingStrategy":"validation","validationCode":"if (bytes == null || bytes.length == 0) {\n  throw new IllegalArgumentException(\"required byte field must be non-empty\");\n}","typeGuard":"static boolean isNonEmpty(ByteString b) { return b != null && !b.isEmpty(); }","tryCatchPattern":"try {\n  grpcStub.call(request);\n} catch (StatusRuntimeException e) {\n  if (e.getStatus().getCode() == Code.INVALID_ARGUMENT && e.getStatus().getDescription().contains(\"non-empty\")) {\n    // generate/load the missing key material and retry\n  }\n}","preventionTips":["Only set bytes fields when real data exists; omit optional fields instead of sending empty","Fail fast client-side when key generation returns zero bytes","Check preconditions of any async operation that produces the byte field before sending the request"],"tags":["grpc","validation","bytes","empty-value"],"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-16T14:17:13.074Z"}