apache/druid · error · IllegalArgumentException
maxValue[ ] must be positive
Error message
maxValue[%s] must be positive
What it means
VSizeLongSerde.getBitsForMax computes the bit width needed to encode values up to the given long; negative values are unsupported, so a negative argument throws IAE 'maxValue must be positive'. Callers must supply a non-negative upper bound.
Solutions
- Fix the max computation to initialize at 0 and use Math.max over the data
- Clamp the argument: Math.max(0, maxValue)
- If negative values are real data, choose a fixed-width signed encoding instead of VSizeLongSerde
Example fix
// before long maxValue = Long.MIN_VALUE; for (long v : vals) maxValue = Math.min(maxValue, v); int bits = VSizeLongSerde.getBitsForMax(maxValue); // after long maxValue = 0; for (long v : vals) maxValue = Math.max(maxValue, v); int bits = VSizeLongSerde.getBitsForMax(maxValue);
Defensive patterns
Strategy: validation
Validate before calling
if (value < 0) throw new IllegalArgumentException("value must be non-negative, got " + value);
int bits = VSizeLongSerde.getBitsForMax(value); Type guard
boolean isValidMaxValue(long v) { return v >= 0; } Try / catch
try { bits = VSizeLongSerde.getBitsForMax(maxValue); } catch (IAE e) { if (e.getMessage().contains("must be positive")) { maxValue = Math.max(0, maxValue); bits = VSizeLongSerde.getBitsForMax(maxValue); } else throw e; } Prevention
- Initialize long max accumulators at 0, not Long.MIN_VALUE
- Filter or map negative sentinels out before column sizing
- Use signed fixed-width encodings when negative data is expected
When it happens
Trigger: Passing a negative long to getBitsForMax, usually from computing a max over data containing negatives or from an accumulator initialized to Long.MIN_VALUE / an erroneous subtraction.
Common situations: Building long dimension/metric columns where sentinel -1 leaked in, or swapping minValue for maxValue in the sizing call.
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
- maxValue[ ] must be positive
- val[ ] > maxValue[ ], please don't lie about maxValue. i[ ]
- A local input source accepts only one of
- A local input source can set parameter
- A local input source requires one parameter of
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/0d65c0a8edc79e58.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/data/VSizeLongSerde.java:47
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Currently only support big endian
* <p>
* An empty 4 bytes is written upon closing to avoid index out of bound exception for deserializers that shift bytes
*/
public class VSizeLongSerde
{
public static final int[] SUPPORTED_SIZES = {1, 2, 4, 8, 12, 16, 20, 24, 32, 40, 48, 56, 64};
public static final byte[] EMPTY = {0, 0, 0, 0};
public static int getBitsForMax(long value)
{
if (value < 0) {
throw new IAE("maxValue[%s] must be positive", value);
}
byte numBits = 0;
long maxValue = 1;
for (int supportedSize : SUPPORTED_SIZES) {
while (numBits < supportedSize && maxValue < Long.MAX_VALUE / 2) {
numBits++;
maxValue *= 2;
}
if (value <= maxValue || maxValue >= Long.MAX_VALUE / 2) {
return supportedSize;
}
}
return 64;
}
public static int getSerializedSize(int bitsPerValue, int numValues)
{
// this value is calculated by rounding up the byte and adding the 4 closing bytesView on GitHub (pinned to 9b90983fd2)