apache/beam · error · IllegalStateException

Unsupported logical type:

Error message

Unsupported logical type: 

What it means

CellValueParser.getCellValue converts a Bigtable cell ByteString back into a Java object based on the declared Beam Schema FieldType. LOGICAL_TYPE fields are not supported for parsing: the parser immediately throws an IllegalStateException naming the logical type's identifier. The library can only decode primitive (STRING/BYTES/numeric/BOOLEAN...) cell values.

Solutions

  1. Change the schema field type to a primitive type (STRING or BYTES) and convert the logical value in user code after reading.
  2. If the logical type is a PassThroughLogicalType, read using its getBaseType() instead of the logical type.
  3. Implement a custom mapper/parse function on BigtableIO.read() instead of relying on schema auto-mapping.

Example fix

// before
Schema.FieldType fieldType = Schema.FieldType.logicalType(MyLogicalType.of());
// after
Schema.FieldType fieldType = Schema.FieldType.STRING;
Row row = ...; // parse MyLogicalType.from(row.getString("col")) in user code
Defensive patterns

Strategy: validation

Validate before calling

for (Schema.Field f : schema.getFields()) {
  if (f.getType().getTypeName() == Schema.TypeName.LOGICAL_TYPE) {
    throw new IllegalArgumentException(
      "Field " + f.getName() + " uses logical type " + f.getType().getLogicalType().getIdentifier()
      + " which BigtableIO cannot parse; use a primitive type.");
  }
}

Type guard

static boolean isParsableCellType(Schema.FieldType t) {
  return t.getTypeName() != Schema.TypeName.LOGICAL_TYPE;
}

Prevention

When it happens

Trigger: Reading Bigtable rows into a Beam schema whose field type is a logical type (e.g. beam:logical_type:javasdk:...) instead of a primitive type, causing the switch in getCellValue to hit case LOGICAL_TYPE and throw.

Common situations: Defining a BigtableIO read with a custom Schema that uses a LogicalType (like a custom enum or datetime logical type) for a column family cell; users assume round-tripping works because writing may pass through via PassThroughLogicalType.

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

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigtable/CellValueParser.java:70

        return Ints.fromByteArray(cellValue.toByteArray());
      case INT64:
        checkArgument(valueSize == 8, message("Int64", 8));
        return Longs.fromByteArray(cellValue.toByteArray());
      case FLOAT:
        checkArgument(valueSize == 4, message("Float", 4));
        return Float.intBitsToFloat(Ints.fromByteArray(cellValue.toByteArray()));
      case DOUBLE:
        checkArgument(valueSize == 8, message("Double", 8));
        return Double.longBitsToDouble(Longs.fromByteArray(cellValue.toByteArray()));
      case DATETIME:
        return DateTime.parse(cellValue.toStringUtf8());
      case STRING:
        return cellValue.toStringUtf8();
      case BYTES:
        return cellValue.toByteArray();
      case LOGICAL_TYPE:
        String identifier = checkArgumentNotNull(type.getLogicalType()).getIdentifier();
        throw new IllegalStateException("Unsupported logical type: " + identifier);
      default:
        throw new IllegalArgumentException(
            String.format("Unsupported cell value type '%s'.", type.getTypeName()));
    }
  }

  ByteString valueToByteString(Object value, Schema.FieldType type) {
    switch (type.getTypeName()) {
      case BOOLEAN:
        return byteString(((Boolean) value) ? new byte[] {1} : new byte[] {0});
      case FLOAT:
        return byteString(Ints.toByteArray(Float.floatToIntBits((Float) value)));
      case DOUBLE:
        return byteString(Longs.toByteArray(Double.doubleToLongBits((Double) value)));
      case BYTE:
        return byteString(new byte[] {(Byte) value});
      case INT16:
        return byteString(Shorts.toByteArray((Short) value));

View on GitHub (pinned to 12126d8942)