zxing/zxing · error · IllegalArgumentException

Illegal value %s for layers

Error message

Illegal value %s for layers

What it means

Thrown by Encoder.encode when userSpecifiedLayers is non-zero and its absolute value exceeds the maximum: 4 for compact mode (negative userSpecifiedLayers) or 32 for full-size mode (positive userSpecifiedLayers). The layer count is out of the valid range. Note: negative values select compact mode, positive values select full-size mode.

Source

Thrown at core/src/main/java/com/google/zxing/aztec/encoder/Encoder.java:137

   * @return Aztec symbol matrix with metadata
   */
  public static AztecCode encode(byte[] data, int minECCPercent, int userSpecifiedLayers, Charset charset) {
    // High-level encode
    BitArray bits = new HighLevelEncoder(data, charset).encode();

    // stuff bits and choose symbol size
    int eccBits = bits.getSize() * minECCPercent / 100 + 11;
    int totalSizeBits = bits.getSize() + eccBits;
    boolean compact;
    int layers;
    int totalBitsInLayer;
    int wordSize;
    BitArray stuffedBits;
    if (userSpecifiedLayers != DEFAULT_AZTEC_LAYERS) {
      compact = userSpecifiedLayers < 0;
      layers = Math.abs(userSpecifiedLayers);
      if (layers > (compact ? MAX_NB_BITS_COMPACT : MAX_NB_BITS)) {
        throw new IllegalArgumentException(
            String.format("Illegal value %s for layers", userSpecifiedLayers));
      }
      totalBitsInLayer = totalBitsInLayer(layers, compact);
      wordSize = WORD_SIZE[layers];
      int usableBitsInLayers = totalBitsInLayer - (totalBitsInLayer % wordSize);
      stuffedBits = stuffBits(bits, wordSize);
      if (stuffedBits.getSize() + eccBits > usableBitsInLayers) {
        throw new IllegalArgumentException("Data to large for user specified layer");
      }
      if (compact && stuffedBits.getSize() > wordSize * 64) {
        // Compact format only allows 64 data words, though C4 can hold more words than that
        throw new IllegalArgumentException("Data to large for user specified layer");
      }
    } else {
      wordSize = 0;
      stuffedBits = null;
      // We look at the possible table sizes in the order Compact1, Compact2, Compact3,
      // Compact4, Normal4,...  Normal(i) for i < 4 isn't typically used since Compact(i+1)

View on GitHub (pinned to 19aa2d8254)

Solutions

  1. Clamp userSpecifiedLayers to the valid range: [-4, -1] for compact, [1, 32] for full-size, or 0 for auto.
  2. Pass DEFAULT_AZTEC_LAYERS (0) to let the encoder auto-select the optimal layer count.
  3. Validate the layer parameter against MAX_NB_BITS (32) and MAX_NB_BITS_COMPACT (4) before calling encode.
  4. Remember the sign convention: negative = compact, positive = full-size.

Example fix

// before
AztecCode code = Encoder.encode(data, 33, -5, charset); // exceeds limits

// after
// Let the encoder auto-select layers (recommended)
AztecCode code = Encoder.encode(data, 33, Encoder.DEFAULT_AZTEC_LAYERS, charset);

// or validate explicitly
int layers = userSpecifiedLayers;
boolean compact = layers < 0;
int maxLayers = compact ? 4 : 32;
if (Math.abs(layers) > maxLayers) {
  throw new IllegalArgumentException("Layers must be within [" + (compact ? -4 : 1) + "," + maxLayers + "]");
}
AztecCode code = Encoder.encode(data, 33, layers, charset);
Defensive patterns

Strategy: validation

Validate before calling

// Validate layer count before encoding
boolean compact = userSpecifiedLayers < 0;
int maxLayers = compact ? 4 : 32;
if (userSpecifiedLayers != 0 && Math.abs(userSpecifiedLayers) > maxLayers) {
  throw new IllegalArgumentException(
    "Layers must be 0 (auto), [-4,-1] compact, or [1,32] full-size");
}

Type guard

boolean isValidLayers(int layers) {
  if (layers == 0) return true; // auto
  boolean compact = layers < 0;
  int max = compact ? 4 : 32;
  return Math.abs(layers) <= max;
}

Try / catch

try {
  AztecCode code = Encoder.encode(data, minECC, userSpecifiedLayers, charset);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Illegal value")) {
    // Re-run with auto-sizing
    code = Encoder.encode(data, minECC, Encoder.DEFAULT_AZTEC_LAYERS, charset);
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Encoder.encode(data, minECCPercent, userSpecifiedLayers) is called with |userSpecifiedLayers| > 4 (compact) or > 32 (full-size). For example, userSpecifiedLayers = -5 (compact mode, 5 layers > MAX_NB_BITS_COMPACT=4) or userSpecifiedLayers = 33 (full-size, 33 > MAX_NB_BITS=32).

Common situations: Passing a layer count derived from user input without clamping to the valid range. A copy-paste error using the wrong constant. Misunderstanding the sign convention (negative = compact). Passing 0 to mean '1 layer' when 0 actually means auto-size.

Related errors


AI-assisted analysis of zxing/zxing@19aa2d8254 (2026-08-14). Data as JSON: /api/errors/a42221eed58684cc. Report an issue: GitHub.