apache/druid · error · java.lang.IllegalArgumentException

not a scalar in the dictionary

Error message

not a scalar in the dictionary

What it means

NestedFieldDictionaryEncodedColumn.lookupGlobalScalarObject() maps a global dictionary id back to its scalar value (null, long, double, or string). The id ranges are partitioned by type; an id beyond the array-id adjustment boundary means it refers to an ARRAY entry, not a scalar, so IllegalArgumentException is thrown - scalars cannot be looked up through this method.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/nested/NestedFieldDictionaryEncodedColumn.java:274

          if (candidate >= 0) {
            candidate += adjustDoubleId;
          }
        }
      }
      return candidate;
    }
  }

  private Object lookupGlobalScalarObject(int globalId)
  {
    if (globalId < adjustLongId) {
      return StringUtils.fromUtf8Nullable(globalDictionary.get(globalId));
    } else if (globalId < adjustDoubleId) {
      return globalLongDictionary.get(globalId - adjustLongId);
    } else if (globalId < adjustArrayId) {
      return globalDoubleDictionary.get(globalId - adjustDoubleId);
    }
    throw new IllegalArgumentException("not a scalar in the dictionary");
  }


  /**
   * Lookup value from appropriate scalar value dictionary, coercing the value to {@link #logicalType}, particularly
   * useful for the vector query engine which prefers all the types are consistent
   * <p>
   * This method should NEVER be used when values must round trip to be able to be looked up from the array value
   * dictionary since it might coerce element values to a different type
   */
  @Nullable
  private Object lookupGlobalScalarValueAndCast(int globalId)
  {

    if (globalId == 0) {
      return null;
    }
    if (singleType != null) {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Filter dictionary ids to the scalar range before calling lookupGlobalScalarObject (id < adjustArrayId).
  2. Use the array-specific lookup path (e.g. lookupArrayGlobalObject / array dictionary APIs) for array-valued ids.
  3. Check code that computes global ids so offsets (adjustLongId, adjustDoubleId, adjustArrayId) are computed from the same metadata version.
  4. If hitting this from a query, cast or restructure the expression so array values are handled as arrays.

Example fix

// before
Object v = column.lookupGlobalScalarObject(globalId); // may be an array id
// after
if (globalId < column.getGlobalArrayIdBase()) {
  Object v = column.lookupGlobalScalarObject(globalId);
} else {
  Object v = column.lookupArrayValue(globalId); // array path
}
Defensive patterns

Strategy: validation

Validate before calling

// only pass ids below the array boundary
if (globalId >= adjustArrayId) {
  throw new IllegalArgumentException("id refers to an array entry; use array lookup");
}

Type guard

boolean isScalarGlobalId(int globalId, int adjustArrayId) { return globalId < adjustArrayId; }

Try / catch

try {
  Object v = col.lookupGlobalScalarObject(globalId);
} catch (IllegalArgumentException e) {
  if ("not a scalar in the dictionary".equals(e.getMessage())) {
    v = col.lookupArrayValue(globalId);
  } throw e;
}

Prevention

When it happens

Trigger: Calling lookupGlobalScalarObject (directly or via lookupObject/eval/getObject on paths that expect scalars) with a global dictionary id that encodes an array value rather than a scalar.

Common situations: Vector/engine code or custom extensions walking all global dictionary ids including array entries; mis-computed id offsets after dictionary merge; querying an ARRAY field through scalar-expectant operators.

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