apache/beam · error · IllegalArgumentException

We currently only support wildcards at terminal parts of sel

Error message

We currently only support wildcards at terminal parts of selectors. 'x.*' is allowed, but x.*.y is not currently allowed.

What it means

FieldAccessDescriptorParser builds a nested FieldAccessDescriptor from a selector string like 'x.*.y'. It walks the parsed components backwards, and if it finds a wildcard ('*') component that is not the terminal (last) component, it throws because nested wildcard expansion is not implemented.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/parser/FieldAccessDescriptorParser.java:83

    @Override
    public FieldAccessDescriptor visitFieldSpecifier(FieldSpecifierContext ctx) {
      return ctx.dotExpression().accept(this);
    }

    @Override
    public FieldAccessDescriptor visitDotExpression(DotExpressionContext ctx) {
      List<FieldAccessDescriptor> components =
          ctx.dotExpressionComponent().stream()
              .map(dotE -> dotE.accept(this))
              .collect(Collectors.toList());

      // Walk backwards through the list to build up the nested FieldAccessDescriptor.
      checkArgument(!components.isEmpty());
      FieldAccessDescriptor fieldAccessDescriptor = components.get(components.size() - 1);
      for (int i = components.size() - 2; i >= 0; --i) {
        FieldAccessDescriptor component = components.get(i);
        if (component.getAllFields()) {
          throw new IllegalArgumentException(
              "We currently only support wildcards at terminal"
                  + " parts of selectors. 'x.*' is allowed, but x.*.y is not currently allowed.");
          // TODO: We should support expanding out x.*.y expressions.
        }
        FieldDescriptor fieldAccessed =
            component.getFieldsAccessed().stream()
                .findFirst()
                .orElseThrow(IllegalArgumentException::new);

        fieldAccessDescriptor =
            FieldAccessDescriptor.withFields()
                .withNestedField(fieldAccessed, fieldAccessDescriptor);
      }
      return fieldAccessDescriptor;
    }

    @Override
    public FieldAccessDescriptor visitQualifyComponent(QualifyComponentContext ctx) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Restructure the selector so the wildcard is terminal: 'x.*' instead of 'x.*.y'.
  2. Expand the wildcard manually: enumerate the actual field names of the nested schema and write them out explicitly, e.g. 'x.a.b', 'x.c.b'.
  3. Use FieldAccessDescriptor.builder() programmatically with explicit field names instead of the string parser.
  4. Check the Beam version/issue tracker: support for 'x.*.y' is a noted TODO and may land in later releases.

Example fix

// before
FieldAccessDescriptor desc = FieldAccessDescriptorParser.parseFrom("x.*.y");
// after
FieldAccessDescriptor desc = FieldAccessDescriptorParser.parseFrom("x.*");
// or explicitly:
FieldAccessDescriptor desc = FieldAccessDescriptor.withFieldNames("x.a.b", "x.c.b");
Defensive patterns

Strategy: validation

Validate before calling

static boolean hasNonTerminalWildcard(String selector) {
  String[] parts = selector.split("\\.");
  for (int i = 0; i < parts.length - 1; i++) {
    if ("*".equals(parts[i])) return true;
  }
  return false;
}
if (hasNonTerminalWildcard(selector)) throw new IllegalArgumentException("wildcard must be terminal");

Type guard

boolean isSafeSelector(String s) { return s != null && !hasNonTerminalWildcard(s); }

Try / catch

try { desc = FieldAccessDescriptorParser.parseFrom(selector); } catch (IllegalArgumentException e) { if (e.getMessage().contains("wildcards")) { /* fall back to explicit field list */ } else throw e; }

Prevention

When it happens

Trigger: Parsing a field selector string via FieldAccessDescriptorParser.parseFrom where a '*' appears in a non-final position, e.g. 'x.*.y' or 'x.*.z.w'.

Common situations: Users of Beam SQL/schema transforms write selector strings assuming glob-like semantics where '*' can appear anywhere, similar to JSONPath or Spark column expansion; the TODO in the source confirms this is an unimplemented feature, not a user error per se.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/0c1d77a7a33b02f2. Report an issue: GitHub.