signalapp/Signal-Server · error · FieldValidationException

byte array length is

Error message

byte array length is [%d] but expected to be one of %s

What it means

ExactlySizeFieldValidator.validateBytesValue checks that a proto bytes field's ByteString is exactly one of a configured set of permitted sizes. If fieldValue.size() is not in permittedSizes, it throws FieldValidationException with a formatted message including the actual and permitted sizes.

Solutions

  1. Check the required length(s) from the error's permitted sizes list and regenerate the value at the correct length
  2. Verify client-side byte arrays are exactly the expected size before encoding into the proto
  3. Ensure the value wasn't truncated/extended by an intermediate encode/decode step
  4. Align client library version with the server's expected field sizes

Example fix

// before
byte[] key = new byte[16];
// after
byte[] key = new byte[32]; // matches permittedSizes [32]
Defensive patterns

Strategy: validation

Validate before calling

if (!permittedSizes.contains(bytes.length)) {
  throw new IllegalArgumentException("expected bytes length in " + permittedSizes + ", got " + bytes.length);
}

Try / catch

try {
  grpcStub.call(request);
} catch (StatusRuntimeException e) {
  if (e.getStatus().getCode() == Code.INVALID_ARGUMENT && e.getStatus().getDescription().contains("byte array length")) {
    // regenerate the bytes at the permitted size
  }
}

Prevention

When it happens

Trigger: gRPC requests with bytes fields (e.g. profile keys, storage keys, receipt data) whose decoded byte length does not match the required size(s) enforced via proto validator annotations.

Common situations: Sending keys of wrong length (e.g. 16 vs 32 bytes) after generating them with a different algorithm; truncating or padding data in client code; version mismatches where the server tightened required sizes.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of signalapp/Signal-Server@100ab61c82 (2026-09-09). Data as JSON: /api/errors/6bf7256fced04c69. Report an issue: GitHub.

Appendix: source

Thrown at service/src/main/java/org/whispersystems/textsecuregcm/grpc/validators/ExactlySizeFieldValidator.java:35

        Descriptors.FieldDescriptor.Type.STRING,
        Descriptors.FieldDescriptor.Type.BYTES
    ), MissingOptionalAction.VALIDATE_DEFAULT_VALUE, true);
  }

  @Override
  protected Set<Integer> resolveExtensionValue(final Object extensionValue) {
    //noinspection unchecked
    return Set.copyOf((List<Integer>) extensionValue);
  }

  @Override
  protected void validateBytesValue(
      final Set<Integer> permittedSizes,
      final ByteString fieldValue) throws FieldValidationException {
    if (permittedSizes.contains(fieldValue.size())) {
      return;
    }
    throw new FieldValidationException("byte array length is [%d] but expected to be one of %s".formatted(fieldValue.size(), permittedSizes));
  }

  @Override
  protected void validateStringValue(
      final Set<Integer> permittedSizes,
      final String fieldValue) throws FieldValidationException {
    if (permittedSizes.contains(fieldValue.length())) {
      return;
    }
    throw new FieldValidationException("string length is [%d] but expected to be one of %s".formatted(fieldValue.length(), permittedSizes));
  }

  @Override
  protected void validateRepeatedField(
      final Set<Integer> permittedSizes,
      final Descriptors.FieldDescriptor fd,
      final List<?> repeated) throws FieldValidationException {
    if (permittedSizes.contains(repeated.size())) {

View on GitHub (pinned to 100ab61c82)