apache/druid · error · org.apache.druid.java.util.common.IAE

maxStringBytes must be greater than 0

Error message

maxStringBytes must be greater than 0

What it means

StringLastAggregatorFactory's constructor validates that maxStringBytes, when supplied, is not negative, throwing IAE with message "maxStringBytes must be greater than 0". maxStringBytes caps the serialized size of stored strings, so a negative value is nonsensical.

Source

Thrown at processing/src/main/java/org/apache/druid/query/aggregation/firstlast/last/StringLastAggregatorFactory.java:111

  private final String fieldName;
  private final String timeColumn;
  private final String name;
  protected final int maxStringBytes;

  @JsonCreator
  public StringLastAggregatorFactory(
      @JsonProperty("name") String name,
      @JsonProperty("fieldName") final String fieldName,
      @JsonProperty("timeColumn") @Nullable final String timeColumn,
      @JsonProperty("maxStringBytes") Integer maxStringBytes
  )
  {
    Preconditions.checkNotNull(name, "Must have a valid, non-null aggregator name");
    Preconditions.checkNotNull(fieldName, "Must have a valid, non-null fieldName");

    if (maxStringBytes != null && maxStringBytes < 0) {
      throw new IAE("maxStringBytes must be greater than 0");
    }

    this.name = name;
    this.fieldName = fieldName;
    this.timeColumn = timeColumn == null ? ColumnHolder.TIME_COLUMN_NAME : timeColumn;
    this.maxStringBytes = maxStringBytes == null
                          ? StringFirstAggregatorFactory.DEFAULT_MAX_STRING_SIZE
                          : maxStringBytes;
  }

  @Override
  public Aggregator factorize(ColumnSelectorFactory metricFactory)
  {
    final BaseObjectColumnValueSelector<?> valueSelector = metricFactory.makeColumnValueSelector(fieldName);
    if (valueSelector instanceof NilColumnValueSelector) {
      return NIL_AGGREGATOR;
    } else {
      return new StringLastAggregator(

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Set maxStringBytes to a positive integer (or omit it to use the default)
  2. Validate the config value before building the aggregation spec
  3. Check where the value originates (query JSON, config file, variable substitution) for a sign or offset bug

Example fix

// before
{"type":"stringLast","name":"last_user","fieldName":"user","maxStringBytes":-1}
// after
{"type":"stringLast","name":"last_user","fieldName":"user","maxStringBytes":1024}
Defensive patterns

Strategy: validation

Validate before calling

if (maxStringBytes != null && maxStringBytes < 0) { throw new IllegalArgumentException("maxStringBytes must be >= 0"); }

Try / catch

try { new StringLastAggregatorFactory(name, field, timeCol, maxBytes); } catch (IAE e) { log.error("Bad maxStringBytes: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Deserializing a JSON aggregation spec with {"type":"stringLast","maxStringBytes":-1} or constructing new StringLastAggregatorFactory(name, fieldName, timeColumn, negativeMaxStringBytes) programmatically. Note the guard actually triggers only for negative values (maxStringBytes < 0), not zero.

Common situations: Hand-written or template-generated native JSON queries with a bad variable substitution producing a negative number; SQL planner or extension code passing an unset/shifted numeric parameter; copying a spec and editing the byte limit incorrectly.

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/ed3386bec8a15759. Report an issue: GitHub.