apache/flink · error · InvalidProgramException
Field expression must be equal to '*' or '_' for atomic type
Error message
Field expression must be equal to '*' or '_' for atomic types.
What it means
Thrown by Keys.ExpressionKeys.isSortKey(String, TypeInformation) when the type is not composite and the expression is not the select-all wildcard. Atomic types (String, Integer, etc.) have no addressable sub-fields, so the only valid sort expression is '*' (Java) or '_' (Scala). Any named-field expression on an atomic type is meaningless.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java:472
throw new IndexOutOfBoundsException("Tuple position is out of range: " + fieldPos);
}
TypeInformation<?> sortKeyType = ((CompositeType<?>) type).getTypeAt(fieldPos);
return sortKeyType.isSortKeyType();
}
public static boolean isSortKey(String fieldExpr, TypeInformation<?> type) {
TypeInformation<?> sortKeyType;
fieldExpr = fieldExpr.trim();
if (SELECT_ALL_CHAR.equals(fieldExpr) || SELECT_ALL_CHAR_SCALA.equals(fieldExpr)) {
sortKeyType = type;
} else {
if (type instanceof CompositeType) {
sortKeyType = ((CompositeType<?>) type).getTypeAt(fieldExpr);
} else {
throw new InvalidProgramException(
"Field expression must be equal to '"
+ SELECT_ALL_CHAR
+ "' or '"
+ SELECT_ALL_CHAR_SCALA
+ "' for atomic types.");
}
}
return sortKeyType.isSortKeyType();
}
}
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
// Utilities
// --------------------------------------------------------------------------------------------
View on GitHub (pinned to 2f3c205e92)
Solutions
- Use isSortKey("*", type) or isSortKey("_", type) for atomic types.
- If a sub-field was intended, first convert the stream to a composite type.
- Branch on type instanceof CompositeType to choose expression vs wildcard.
Example fix
// before
Keys.ExpressionKeys.isSortKey("value", BasicTypeInfo.STRING_TYPE_INFO);
// after
Keys.ExpressionKeys.isSortKey("*", BasicTypeInfo.STRING_TYPE_INFO); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(type instanceof CompositeType)
&& !("*".equals(fieldExpr.trim()) || "_".equals(fieldExpr.trim()))) {
throw new IllegalArgumentException(
"Atomic type requires '*' or '_' as sort expression.");
} Type guard
static boolean isValidSortExprForAtomic(String expr) {
String t = expr.trim();
return "*".equals(t) || "_".equals(t);
} Prevention
- Use '*' or '_' for atomic-type sort expressions.
- Branch on type instanceof CompositeType before choosing expression style.
- Do not reuse POJO field names on scalar streams.
When it happens
Trigger: Calling isSortKey("myField", stringTypeInfo) where the type is a String or primitive wrapper. Higher-level sort APIs that call this with a user-provided field name on a non-composite stream.
Common situations: Reusing a field-name string meant for a POJO on a stream that turned out to be a primitive. Forgetting that scalar streams require wildcard expressions.
Related errors
- Local output sorting does not support type {inputType} yet.
- Specifying keys via field positions is only valid for tuple
- This type ({ffd.getType()}) cannot be used as key.
- This type ({field.getType()}) cannot be used as key.
- This type ({type}) cannot be used as key.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/25619e2bf4cbe570.
Report an issue: GitHub.