{"record":{"id":"bb0548266d90df0d","repo":"apache/beam","slug":"unsupported-logical-type-s","errorCode":null,"errorMessage":"Unsupported logical type: %s","messagePattern":"Unsupported logical type: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/MutationUtils.java","lineNumber":260,"sourceCode":"        // BigDecimal is not nullable\n        if (decimal == null) {\n          checkNotNull(decimal, \"Null decimal at column %s\", columnName);\n        } else {\n          mutationBuilder.set(columnName).to(decimal);\n        }\n        break;\n      case LOGICAL_TYPE:\n        Schema.LogicalType<?, ?> logicalType = checkNotNull(fieldType.getLogicalType());\n        String identifier = logicalType.getIdentifier();\n        if (identifier.equals(MicrosInstant.IDENTIFIER)) {\n          @Nullable Instant instant = row.getValue(columnName);\n          if (instant == null) {\n            mutationBuilder.set(columnName).to((Timestamp) null);\n          } else {\n            mutationBuilder.set(columnName).to(toSpannerTimestamp(instant));\n          }\n        } else {\n          throw new IllegalArgumentException(\n              String.format(\"Unsupported logical type: %s\", identifier));\n        }\n        break;\n      case DATETIME:\n        @Nullable ReadableDateTime dateTime = row.getDateTime(columnName);\n        if (dateTime == null) {\n          mutationBuilder.set(columnName).to(((Timestamp) null));\n        } else {\n          mutationBuilder\n              .set(columnName)\n              .to(Timestamp.ofTimeMicroseconds(dateTime.toInstant().getMillis() * 1000L));\n        }\n        break;\n      case BOOLEAN:\n        mutationBuilder.set(columnName).to(row.getBoolean(columnName));\n        break;\n      case STRING:\n        mutationBuilder.set(columnName).to(row.getString(columnName));","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/MutationUtils.java#L242-L278","documentation":"MutationUtils.setBeamValueToMutation() maps Beam Row field values into a Spanner mutation builder, switching on the field's logical type identifier. A logical type with no mapping (ARRAY, MAP, custom logical types, etc.) throws IllegalArgumentException('Unsupported logical type: %s') because Spanner mutations do not accept such values.","triggerScenarios":"Writing a Beam Row whose schema contains a field with an unmapped logical type (e.g. array, map, row, or a custom LogicalType) through the Spanner sink's createMutationFromBeamRows path.","commonSituations":"Auto-generated schemas from sources with nested/repeated fields (e.g. BigQuery RECORD, Avro unions) piped into a Spanner write; adding a new custom LogicalType to the schema without extending MutationUtils.","solutions":["Map unsupported logical types to supported Spanner types (encode arrays/maps/structs as JSON STRING).","Flatten nested fields into separate scalar columns before the write.","If you own a custom LogicalType, add a case for it (or convert to its base type) before writing."],"exampleFix":"// before\nFieldType listField = FieldType.array(FieldType.string) // unsupported in mutation path\n// after\nFieldType listField = FieldType.STRING // store JSON-encoded array","handlingStrategy":"validation","validationCode":"for (Field f : row.getSchema().getFields()) {\n  String id = f.getType().getNullableSupplement().getIdentifier();\n  if (Set.of(\"array\",\"map\",\"row\",\"iterable\").contains(id.toLowerCase()))\n    throw new IllegalArgumentException(\"flatten field before Spanner write: \" + f.getName());\n}","typeGuard":"boolean isMutationWritable(Field f) { return !f.getType().getTypeName().isCollectionType() && !f.getType().getTypeName().isCompositeType() && !f.getType().getTypeName().isMapType(); }","tryCatchPattern":"try { mutation = MutationUtils.createMutationFromBeamRows(builder, row); } catch (IllegalArgumentException e) { /* encode field as JSON string and retry */ }","preventionTips":["Flatten/normalize schemas before Spanner sink","Encode nested structures as JSON STRING columns","Keep a mapping test covering every field logical type in your schema"],"tags":["java","apache-beam","spanner","schema"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}