apache/druid · error · IllegalArgumentException

Empty or null virtualColumn name

Error message

Empty or null virtualColumn name

What it means

VirtualColumns.fromIterable validates each VirtualColumn's output name. A virtual column with a null or empty output name cannot be referenced in queries, so an IAE is thrown at construction time. Every virtual column must have a non-empty, unique output name distinct from __time.

Solutions

  1. Set an explicit outputName on every VirtualColumn in the query
  2. Check query JSON for virtualColumns entries missing the "name"/outputName field
  3. Update query-builder code to require a non-empty name (Objects.requireNonNull) before constructing columns

Example fix

// before
ExpressionVirtualColumn vc = new ExpressionVirtualColumn(null, "x + 1", ValueType.LONG, exprMacroTable);
// after
ExpressionVirtualColumn vc = new ExpressionVirtualColumn("v:x_plus_1", "x + 1", ValueType.LONG, exprMacroTable);
Defensive patterns

Strategy: validation

Validate before calling

for (VirtualColumn vc : virtualColumns) {
  if (Strings.isNullOrEmpty(vc.getOutputName())) {
    throw new IllegalArgumentException("Virtual column requires non-empty outputName");
  }
}

Try / catch

try {
  VirtualColumns.fromIterable(cols);
} catch (IAE e) {
  log.error(e, "Bad virtual column config");
}

Prevention

When it happens

Trigger: Calling VirtualColumns.fromIterable (or create) with a VirtualColumn whose getOutputName() returns null or "" — commonly a misconfigured expression or lookup virtual column in a query.

Common situations: Hand-written native queries omitting the expression outputName; deserialized queries from clients where the name field was dropped; programmatic query builders leaving names unset.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/VirtualColumns.java:112

  {
    if (virtualColumns == null || virtualColumns.isEmpty()) {
      return EMPTY;
    }
    return fromIterable(virtualColumns);
  }

  public static VirtualColumns create(VirtualColumn... virtualColumns)
  {
    return create(Arrays.asList(virtualColumns));
  }

  public static VirtualColumns fromIterable(Iterable<VirtualColumn> virtualColumns)
  {
    Map<String, VirtualColumn> withDotSupport = new HashMap<>();
    Map<String, VirtualColumn> withoutDotSupport = new HashMap<>();
    for (VirtualColumn vc : virtualColumns) {
      if (Strings.isNullOrEmpty(vc.getOutputName())) {
        throw new IAE("Empty or null virtualColumn name");
      }

      if (vc.getOutputName().equals(ColumnHolder.TIME_COLUMN_NAME)) {
        throw new IAE("virtualColumn name[%s] not allowed", vc.getOutputName());
      }

      if (withDotSupport.containsKey(vc.getOutputName()) || withoutDotSupport.containsKey(vc.getOutputName())) {
        throw new IAE("Duplicate virtualColumn name[%s]", vc.getOutputName());
      }

      if (vc.usesDotNotation()) {
        withDotSupport.put(vc.getOutputName(), vc);
      } else {
        withoutDotSupport.put(vc.getOutputName(), vc);
      }
    }
    return new VirtualColumns(ImmutableList.copyOf(virtualColumns), withDotSupport, withoutDotSupport);
  }

View on GitHub (pinned to 9b90983fd2)