apache/beam · error · IllegalStateException
No fields were set for input ${tag}
Error message
No fields were set for input ${tag} What it means
CoGroup.from builds the transform's key schemas by looking up, for each input PCollection tag, the FieldAccessDescriptor supplied via join clauses. If a tag in the PCollectionTuple has no corresponding field descriptor, it throws IllegalStateException, since every input must define its join key fields.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/transforms/CoGroup.java:383
.map(TupleTag::getId)
.sorted()
.collect(Collectors.toList());
// Keep this in a TreeMap so that it's sorted. This way we get a deterministic output
// schema.
TreeMap<String, Schema> componentSchemas = Maps.newTreeMap();
Map<String, PCollectionView<Map<Row, Iterable<Row>>>> sideInputs = Maps.newHashMap();
Map<Integer, String> tagToKeyedTag = Maps.newHashMap();
Schema keySchema = null;
for (Map.Entry<TupleTag<?>, PCollection<?>> entry : input.getAll().entrySet()) {
String tag = entry.getKey().getId();
PCollection<?> pc = entry.getValue();
Schema schema = pc.getSchema();
componentSchemas.put(tag, schema);
FieldAccessDescriptor fieldAccessDescriptor = getFieldAccessDescriptor.apply(tag);
if (fieldAccessDescriptor == null) {
throw new IllegalStateException("No fields were set for input " + tag);
}
// Resolve the key schema, keeping the fields in the order specified by the user.
// Otherwise, if different field names are specified for different PCollections, they
// might not match up.
// The key schema contains the field names from the first PCollection specified.
FieldAccessDescriptor resolved = fieldAccessDescriptor.resolve(schema);
Schema currentKeySchema = SelectHelpers.getOutputSchema(schema, resolved);
if (keySchema == null) {
keySchema = currentKeySchema;
} else {
keySchema = SchemaUtils.mergeWideningNullable(keySchema, currentKeySchema);
}
}
// Second loop so we can widen the keySchema with every input before using it
for (Map.Entry<TupleTag<?>, PCollection<?>> entry : input.getAll().entrySet()) {
String tag = entry.getKey().getId();
int tagIndex = sortedTags.indexOf(tag);
PCollection<?> pc = entry.getValue();View on GitHub (pinned to 12126d8942)
Solutions
- Add a join(tag, By.field(...)) clause for every tag present in the PCollectionTuple.
- Verify tag ids: TupleTag.getId() must exactly match the tag strings used in join() calls.
- Use the global byFields(...) variant if all inputs should use the same key fields, instead of per-tag clauses.
- Print input.getAll().keySet() and the join args map and diff them before building the transform.
Example fix
// before (tag "c" in tuple, no clause)
CoGroup join = CoGroup
.join("a", By.field("key")).join("b", By.field("key"))
.from(tuple); // throws: no fields for "c"
// after
CoGroup join = CoGroup
.join("a", By.field("key")).join("b", By.field("key"))
.join("c", By.field("key"))
.from(tuple); Defensive patterns
Strategy: validation
Validate before calling
Set<String> tags = tuple.getAll().keySet().stream().map(TupleTag::getId).collect(Collectors.toSet());
Set<String> joined = joinArgsMap.keySet();
if (!tags.equals(joined)) throw new IllegalStateException("missing join clauses for tags: " + Sets.difference(tags, joined)); Try / catch
try { CoGroup g = builder.from(tuple); } catch (IllegalStateException e) { if (e.getMessage().startsWith("No fields were set for input")) { /* add missing join(tag,...) */ } else throw e; } Prevention
- Always build per-tag join clauses from tuple.getAll().keySet() programmatically
- Compare TupleTag.getId() strings, never assume object identity
- Add a pre-flight assertion comparing tag sets before from()
When it happens
Trigger: Constructing CoGroup via CoGroup.from(tuple) where the Impl's join fields were set with byFieldDescriptors (a map keyed by tag) that is missing an entry for one of the tuple's tags — e.g. joins specified for tags 'a' and 'b' but the tuple also contains tag 'c'.
Common situations: Forgetting a per-tag .join(tag, By.field(...)) call before expanding; adding a third input PCollection to the tuple without adding a matching join clause; tag name typos (TupleTag id differs from the string used in join).
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- The input PCollectionTuple has tags: ${inputTags} and the jo
- Cannot set both a global and per-tag fields.
- union tag ${unionTag} has no corresponding tuple tag in the
- TupleTag ${tag} is not in the schema
- Unexpected join type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/8bff5f220c7833da.
Report an issue: GitHub.