apache/beam · error · java.lang.IllegalStateException

Unreachable case for Beam typename %s

Error message

Unreachable case for Beam typename %s

What it means

fieldToAvatica switches over Beam FieldType.getTypeName() to produce JDBC-friendly values. The default branch is supposed to be unreachable because all Beam TypeNames are handled; hitting IllegalStateException("Unreachable case for Beam typename %s") means a FieldType with a TypeName the converter doesn't recognize reached the row-conversion path — typically a new/custom or logical element type added after this code was written.

Source

Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamEnumerableConverter.java:376

                .map(elem -> fieldToAvatica(type.getCollectionElementType(), elem))
                .collect(Collectors.toList());
      case ITERABLE:
        return StreamSupport.stream(((Iterable<?>) beamValue).spliterator(), false)
            .map(elem -> fieldToAvatica(type.getCollectionElementType(), elem))
            .collect(Collectors.toList());
      case MAP:
        return ((Map<?, ?>) beamValue)
            .entrySet().stream()
                .collect(
                    Collectors.toMap(
                        entry -> entry.getKey(),
                        entry ->
                            fieldToAvatica(type.getCollectionElementType(), entry.getValue())));
      case ROW:
        // TODO: needs to be a Struct
        return beamValue;
      default:
        throw new IllegalStateException(
            String.format("Unreachable case for Beam typename %s", type.getTypeName()));
    }
  }

  private static Enumerable<Object> count(PipelineOptions options, BeamRelNode node) {
    Pipeline pipeline = Pipeline.create(options);
    BeamSqlRelUtils.toPCollection(pipeline, node).apply(ParDo.of(new RowCounter()));
    PipelineResult result = pipeline.run();

    long count = 0;
    if (!containsUnboundedPCollection(pipeline)) {
      if (PipelineResult.State.FAILED.equals(result.waitUntilFinish())) {
        throw new RuntimeException("Pipeline failed for unknown reason");
      }
      MetricQueryResults metrics =
          result
              .metrics()
              .queryMetrics(

View on GitHub (pinned to 12126d8942)

Solutions

  1. Identify the offending TypeName from the message and change the column type to a supported primitive (INT32, STRING, DATETIME, etc.) in the schema
  2. Avoid exotic logical types in columns exposed to Beam SQL; cast/coerce to supported types upstream
  3. File/apply an upstream fix adding a case for the missing TypeName in fieldToAvatica
  4. Check Beam SDK version compatibility between the component producing the schema and the SQL extension

Example fix

// before: schema with unsupported field
Schema schema = Schema.builder().addInt64Field("id").addFieldType("x", unsupportedType).build();
// after: coerce to a supported type
Schema schema = Schema.builder().addInt64Field("id").addStringField("x").build();
Defensive patterns

Strategy: type-guard

Validate before calling

for (Field f : schema.getFields()) {
  switch (f.getType().getTypeName()) {
    case BYTE: case INT16: case INT32: case INT64: case FLOAT: case DOUBLE:
    case STRING: case DATETIME: case BOOLEAN: case DECIMAL: case ARRAY:
    case MAP: case ITERABLE: case ROW:
      break;
    default:
      throw new IllegalArgumentException("Field '" + f.getName()
          + "' has unsupported type " + f.getType().getTypeName());
  }
}

Type guard

static final Set<TypeName> SUPPORTED = EnumSet.of(TypeName.BYTE, TypeName.INT16,
    TypeName.INT32, TypeName.INT64, TypeName.FLOAT, TypeName.DOUBLE, TypeName.STRING,
    TypeName.DATETIME, TypeName.BOOLEAN, TypeName.DECIMAL, TypeName.ARRAY,
    TypeName.MAP, TypeName.ITERABLE, TypeName.ROW);
boolean isAvaticaConvertible(FieldType t) { return SUPPORTED.contains(t.getTypeName()); }

Try / catch

try {
  Object v = fieldToAvatica(type, value);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Unreachable case for Beam typename")) {
    // coerce value to string/primitive or skip field
  } else throw e;
}

Prevention

When it happens

Trigger: SELECTing a column (or nested collection/row element) whose Beam FieldType TypeName falls through the switch — e.g. a recently added Beam TypeName, an exotic logical-typed field inside arrays/maps, or a schema produced by custom IO connectors.

Common situations: Upgrading Beam SDK so schemas contain new types while the SQL extension converter lags behind; using custom logical types in table schemas queried through the JDBC/Calcite interface; returning POJO/Avro-derived schemas with unusual field types from a SELECT.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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