apache/beam · error · IllegalArgumentException

Unable to translate beam type %s to Spanner type

Error message

Unable to translate beam type %s to Spanner type

What it means

simpleBeamTypeToSpannerType maps scalar Beam field types to Cloud Spanner Type objects for schema creation. Unmapped types (everything past the supported set) raise this IllegalArgumentException. Note DATETIME is mapped to Type.timestamp(); truly unsupported types like DECIMAL or MAP hit the default branch.

Source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/StructUtils.java:266

      case INT64:
      case INT32:
      case INT16:
        return Type.int64();
      case DOUBLE:
        return Type.float64();
      case FLOAT:
        return Type.float32();
      case DECIMAL:
        return Type.numeric();
      case STRING:
        return Type.string();
      case BOOLEAN:
        return Type.bool();
        // TODO: implement logical type date and timestamp
      case DATETIME:
        return Type.timestamp();
      default:
        throw new IllegalArgumentException(
            String.format(
                "Unable to translate beam type %s to Spanner type", beamType.getTypeName()));
    }
  }

  private static Iterable<Type.StructField> translateRowFieldsToStructFields(
      List<Schema.Field> rowFields) {
    return rowFields.stream()
        .map(field -> Type.StructField.of(field.getName(), beamTypeToSpannerType(field.getType())))
        .collect(toList());
  }

  @SuppressWarnings("unchecked")
  private static void addIterableToStructBuilder(
      Struct.Builder structBuilder, @Nullable Iterable<Object> iterable, Schema.Field field) {
    String column = field.getName();
    Schema.FieldType beamIterableType = field.getType().getCollectionElementType();
    if (beamIterableType == null) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Convert the unsupported field to a supported Beam type before writing (e.g. DECIMAL to STRING, or DATETIME for timestamps).
  2. Pre-convert complex types (maps, bytes) to STRING/JSON-compatible representations.
  3. Check the supported-type list in StructUtils and adjust your Schema to match it.

Example fix

// before
Schema.Field.of("amount", Schema.FieldType.DECIMAL)
// after
Schema.Field.of("amount", Schema.FieldType.STRING) // or convert to DATETIME-compatible representation
Defensive patterns

Strategy: type-guard

Type guard

boolean isSpannerWritable(Schema.FieldType t) {
  switch (t.getTypeName()) {
    case STRING: case INT64: case FLOAT64: case BOOLEAN: case DATETIME:
      return true;
    default:
      return false;
  }
}

Prevention

When it happens

Trigger: Calling beamTypeToSpannerType (e.g. when writing rows or creating Spanner tables from a Beam schema) with a Beam FieldType such as DECIMAL, BYTES, MAP, or a custom logical type not covered by simpleBeamTypeToSpannerType.

Common situations: Writing PCollections with NUMERIC/decimal columns to Spanner; schemas containing bytes or map fields; Beam logical types like Json or custom types.

Related errors


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