apache/druid · error · IllegalStateException

Ambiguous directions

Error message

Ambiguous directions[%s] and [%s]

What it means

OrderByColumnSpec.fromString parses a direction string (e.g. "asc", "desc", "ascending") by prefix-matching against Direction enum names. If the input prefix matches more than one Direction value, the parse is ambiguous and this ISE is thrown instead of silently picking one.

Solutions

  1. Use the full, unambiguous direction name: "ascending" (or "ASC") / "descending" (or "DESC")
  2. Use an exact enum value from STUPID_ENUM_MAP (case-insensitive) rather than a prefix
  3. Validate user-provided direction strings against Direction.values() before constructing the spec

Example fix

// before
OrderByColumnSpec.fromString("myCol", "d") // ambiguous
// after
OrderByColumnSpec.fromString("myCol", "descending")
Defensive patterns

Strategy: type-guard

Validate before calling

Direction parseDirection(String s) {
  String u = s.toUpperCase(Locale.ROOT);
  if ("ASCENDING".startsWith(u)) return Direction.ASCENDING;
  if ("DESCENDING".startsWith(u)) return Direction.DESCENDING;
  throw new IllegalArgumentException("Ambiguous or invalid direction: " + s);
}

Type guard

boolean isExplicitDirection(String s) {
  String u = s == null ? "" : s.toUpperCase(Locale.ROOT);
  return u.equals("ASC") || u.equals("ASCENDING") || u.equals("DESC") || u.equals("DESCENDING");
}

Try / catch

try {
  spec = OrderByColumnSpec.fromString(col, dirStr);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Ambiguous directions")) {
    spec = OrderByColumnSpec.fromString(col, "DESCENDING"); // or surface a validation error to the user
  } else throw e;
}

Prevention

When it happens

Trigger: Calling OrderByColumnSpec.fromString or constructing a spec from a JSON direction string that is a prefix of multiple Direction names (e.g. a string starting with "d" that matches both DESCENDING and another value, or any non-unique prefix).

Common situations: Hand-written native JSON queries using abbreviated direction strings like "d" or "de", user-supplied sort input passed through from an application, or typos in direction names in serialized query specs.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/query/groupby/orderby/OrderByColumnSpec.java:82

    @JsonValue
    @Override
    public String toString()
    {
      return StringUtils.toLowerCase(this.name());
    }

    @JsonCreator
    public static Direction fromString(String name)
    {
      final String upperName = StringUtils.toUpperCase(name);
      Direction direction = STUPID_ENUM_MAP.get(upperName);

      if (direction == null) {
        for (Direction dir : Direction.values()) {
          if (dir.name().startsWith(upperName)) {
            if (direction != null) {
              throw new ISE("Ambiguous directions[%s] and [%s]", direction, dir);
            }
            direction = dir;
          }
        }
      }

      return direction;
    }
  }

  public static final StringComparator DEFAULT_DIMENSION_ORDER = StringComparators.LEXICOGRAPHIC;

  private final String dimension;
  private final Direction direction;
  private final StringComparator dimensionComparator;

  @JsonCreator
  public OrderByColumnSpec(

View on GitHub (pinned to 9b90983fd2)