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
- Restructure the selector so the wildcard is terminal: 'x.*' instead of 'x.*.y'.
- 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'.
- Use FieldAccessDescriptor.builder() programmatically with explicit field names instead of the string parser.
- 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
- Keep '*' as the last component of any selector
- Enumerate nested schema field names explicitly instead of using mid-path wildcards
- Unit-test selector strings against FieldAccessDescriptorParser before pipeline launch
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
- Cannot select a subfield of a non-composite type.
- Unexpected field type
- Timing number 0b" + timingNumber.toString(2) + " has more th
- No proto encoding for PaneInfoCoder, always part of Windowed
- Runner does not support draining.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/0c1d77a7a33b02f2.
Report an issue: GitHub.