apache/beam · error · IllegalStateException

Cannot set both a global and per-tag fields.

Error message

Cannot set both a global and per-tag fields.

What it means

CoGroup supports either a global key-fields clause (byFields applying to all inputs) or per-tag join(tag, By) clauses, but not both. The Impl's join() method throws IllegalStateException if joinArgs.allInputsJoinArgs was already set, enforcing this mutual exclusivity.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/transforms/CoGroup.java:728

    }

    private Impl(JoinArguments joinArgs, String keyFieldName) {
      this.joinArgs = joinArgs;
      this.keyFieldName = keyFieldName;
    }

    public Impl withKeyField(String keyFieldName) {
      return new Impl(joinArgs, keyFieldName);
    }

    /**
     * Select the following fields for the specified PCollection with the specified join args.
     *
     * <p>Each PCollection in the input must have fields specified for the join key.
     */
    public Impl join(String tag, By clause) {
      if (joinArgs.allInputsJoinArgs != null) {
        throw new IllegalStateException("Cannot set both a global and per-tag fields.");
      }
      return new Impl(joinArgs.with(tag, clause), keyFieldName);
    }

    /** Expand the join into individual rows, similar to SQL joins. */
    public ExpandCrossProduct crossProductJoin() {
      return new ExpandCrossProduct(joinArgs);
    }

    @Override
    public PCollection<Row> expand(PCollectionTuple input) {
      verify(input, joinArgs);

      JoinInformation joinInformation =
          JoinInformation.from(
              input, joinArgs::getFieldAccessDescriptor, joinArgs::getSideInputSource);

      Collection<PCollectionView<Map<Row, Iterable<Row>>>> views =

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use per-tag join(tag, By...) for ALL inputs, dropping the global byFields() call.
  2. Or keep the global byFields() and remove all join(tag, ...) calls if all inputs share the same key fields.
  3. Model per-input customization by giving each tag its own By clause that duplicates the common fields plus extras.

Example fix

// before (mixing)
CoGroup coGroup = CoGroup.byFields("key")
    .join("b", By.field("otherKey"))
    .from(tuple);
// after: all per-tag
CoGroup coGroup = CoGroup
    .join("a", By.field("key"))
    .join("b", By.field("otherKey"))
    .from(tuple);
Defensive patterns

Strategy: validation

Validate before calling

if (usedGlobalByFields && perTagJoinsUsed) {
  throw new IllegalStateException("Cannot set both a global and per-tag fields.");
}

Try / catch

try { impl = builder.join(tag, by); } catch (IllegalStateException e) { if (e.getMessage().contains("global and per-tag")) { /* rebuild builder with one style */ } else throw e; }

Prevention

When it happens

Trigger: Calling CoGroup.byFields(...).join("tag", By.field(...)) — i.e. mixing the global byFields() call with any per-tag join() call on the same builder.

Common situations: Starting a join with the convenient global byFields() and later trying to customize one input's key fields; copy-pasting builder code that combines both styles from examples.

Related errors


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