apache/druid · error · IllegalArgumentException

maxValue[ ] must be positive

Error message

maxValue[%s] must be positive

What it means

VSizeColumnarInts.getNumBytesForMax computes how many bytes are needed to store values up to maxValue; a negative maxValue is meaningless for sizing, so it throws IAE immediately. Callers (e.g. numBytes) must pass a non-negative maxValue.

Solutions

  1. Fix the maxValue computation to initialize at 0 or guard against empty input
  2. Clamp: pass Math.max(0, maxValue)
  3. Validate the computed maxValue before calling getNumBytesForMax

Example fix

// before
int maxValue = Integer.MIN_VALUE; for (int v : vals) maxValue = Math.min(maxValue, v); // wrong function
byte numBytes = VSizeColumnarInts.getNumBytesForMax(maxValue);
// after
int maxValue = 0; for (int v : vals) maxValue = Math.max(maxValue, v);
byte numBytes = VSizeColumnarInts.getNumBytesForMax(maxValue);
Defensive patterns

Strategy: validation

Validate before calling

if (maxValue < 0) throw new IllegalArgumentException("maxValue must be non-negative, got " + maxValue);
byte numBytes = VSizeColumnarInts.getNumBytesForMax(maxValue);

Type guard

boolean isValidMaxValue(long v) { return v >= 0 && v <= Integer.MAX_VALUE; }

Try / catch

try { numBytes = VSizeColumnarInts.getNumBytesForMax(maxValue); } catch (IAE e) { if (e.getMessage().contains("must be positive")) { maxValue = Math.max(0, maxValue); numBytes = VSizeColumnarInts.getNumBytesForMax(maxValue); } else throw e; }

Prevention

When it happens

Trigger: Passing a negative maxValue to getNumBytesForMax, typically because maxValue was derived from data containing negatives or from an uninitialized/min-initialized accumulator (e.g. Integer.MIN_VALUE from Math.min over an empty set).

Common situations: Computing max with an initial value of Integer.MIN_VALUE when the dataset is empty, or reusing a minValue instead of maxValue variable.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/4a034fcf183e3d21. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/data/VSizeColumnarInts.java:87

    for (int i = 0, size = ints.size(); i < size; i++) {
      int val = ints.get(i);
      if (val < 0) {
        throw new IAE("integer values must be positive, got[%d], i[%d]", val, i);
      }
      if (val > maxValue) {
        throw new IAE("val[%d] > maxValue[%d], please don't lie about maxValue.  i[%d]", val, maxValue, i);
      }

      helperBuffer.putInt(0, val);
      buffer.put(helperBuffer.array(), Integer.BYTES - numBytes, numBytes);
    }
    buffer.position(0);
  }

  public static byte getNumBytesForMax(int maxValue)
  {
    if (maxValue < 0) {
      throw new IAE("maxValue[%s] must be positive", maxValue);
    }

    if (maxValue <= 0xFF) {
      return 1;
    } else if (maxValue <= 0xFFFF) {
      return 2;
    } else if (maxValue <= 0xFFFFFF) {
      return 3;
    }
    return 4;
  }

  private final ByteBuffer buffer;
  private final int numBytes;

  private final int bitsToShift;
  private final int size;

View on GitHub (pinned to 9b90983fd2)