apache/beam · error · UnsupportedOperationException

Does not support

Error message

Does not support %s

What it means

SerializableRexFieldAccess serializes a Calcite RexFieldAccess chain for use in DoFns. While walking the chain, the reference expression of the final/current node must be a RexInputRef; any other RexNode type (e.g. RexCall) triggers UnsupportedOperationException with the type's toString. Only simple field accesses over an input row are supported.

Solutions

  1. Ensure the RexFieldAccess refers to a plain input column; pre-compute/cast expressions in an upstream Project so the access target is a RexInputRef.
  2. Insert an additional projection (e.g. via Project/RexProgram) to materialize computed values into input refs before creating SerializableRexFieldAccess.
  3. Check the plan and avoid applying SerializableRexFieldAccess to nodes with RexCall references.
  4. Extend the class to handle the specific RexNode type if you control the pipeline.

Example fix

// before
SerializableRexFieldAccess access = new SerializableRexFieldAccess(rexCallAccess, rowTypeInfo); // reference is RexCall
// after
// materialize the expression in a preceding Project so the access is over a RexInputRef
RexNode projected = rexBuilder.makeInputRef(computedType, computedIndex);
SerializableRexFieldAccess access = new SerializableRexFieldAccess(rexBuilder.makeFieldAccess(projected, 0), rowTypeInfo);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!(rexFieldAccess.getReferenceExpr() instanceof RexInputRef)) {
  throw new IllegalArgumentException("SerializableRexFieldAccess only supports RexInputRef references");
}

Type guard

boolean isSerializableFieldAccess(RexFieldAccess fa) {
  return fa.getReferenceExpr() instanceof RexInputRef;
}

Try / catch

try { access = new SerializableRexFieldAccess(rexFieldAccess, rowTypeInfo); }
catch (UnsupportedOperationException e) { /* materialize expression in a preceding Project, then retry */ }

Prevention

When it happens

Trigger: Constructing new SerializableRexFieldAccess(rexFieldAccess, rowTypeInfo) where some node in the access chain's getReferenceExpr() is not a RexInputRef — e.g. the accessed field is the result of a Calcite expression (RexCall like CAST or arithmetic) rather than a plain input column.

Common situations: Beam SQL plans where a correlating/subquery expression accesses computed columns (casted or computed field accesses) instead of raw input refs; using field accesses from optimized/rewritten plans.

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/c106d40419ab11cc. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/utils/SerializableRexFieldAccess.java:41

import org.apache.beam.vendor.calcite.v1_40_0.org.apache.calcite.rex.RexFieldAccess;
import org.apache.beam.vendor.calcite.v1_40_0.org.apache.calcite.rex.RexInputRef;

/** SerializableRexFieldAccess. */
public class SerializableRexFieldAccess extends SerializableRexNode {
  private List<Integer> indexes = new ArrayList<>();

  public SerializableRexFieldAccess(RexFieldAccess rexFieldAccess) {
    indexes.add(rexFieldAccess.getField().getIndex());
    RexFieldAccess curr = rexFieldAccess;
    while (curr.getReferenceExpr() instanceof RexFieldAccess) {
      curr = (RexFieldAccess) curr.getReferenceExpr();
      indexes.add(rexFieldAccess.getField().getIndex());
    }

    // curr.getReferenceExpr() is not a RexFieldAccess. Check if it is RexInputRef, which is only
    // allowed RexNode type in RexFieldAccess.
    if (!(curr.getReferenceExpr() instanceof RexInputRef)) {
      throw new UnsupportedOperationException(
          "Does not support " + curr.getReferenceExpr().getType());
    }

    // curr.getReferenceExpr() is a RexInputRef.
    RexInputRef inputRef = (RexInputRef) curr.getReferenceExpr();
    indexes.add(inputRef.getIndex());

    Collections.reverse(indexes);
  }

  public List<Integer> getIndexes() {
    return indexes;
  }
}

View on GitHub (pinned to 12126d8942)