{"record":{"id":"82e3a037cd9dc863","repo":"apache/beam","slug":"unsupported-field-type-s-mutationutils","errorCode":null,"errorMessage":"Unsupported field type: %s","messagePattern":"Unsupported field 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":196,"sourceCode":"              Timestamp.ofTimeMicroseconds(dateTime.toInstant().getMillis() * 1_000L));\n        }\n        break;\n      case BOOLEAN:\n        keyBuilder.append(row.getBoolean(columnName));\n        break;\n      case STRING:\n        keyBuilder.append(row.getString(columnName));\n        break;\n      case BYTES:\n        byte @Nullable [] bytes = row.getBytes(columnName);\n        if (bytes == null) {\n          keyBuilder.append((ByteArray) null);\n        } else {\n          keyBuilder.append(ByteArray.copyFrom(bytes));\n        }\n        break;\n      default:\n        throw new IllegalArgumentException(\n            String.format(\"Unsupported field type: %s\", field.getTypeName()));\n    }\n  }\n\n  private static void setBeamValueToMutation(\n      Mutation.WriteBuilder mutationBuilder,\n      Schema.FieldType fieldType,\n      String columnName,\n      Row row) {\n    switch (fieldType.getTypeName()) {\n      case BYTE:\n        @Nullable Byte byteValue = row.getByte(columnName);\n        if (byteValue == null) {\n          mutationBuilder.set(columnName).to(((Long) null));\n        } else {\n          mutationBuilder.set(columnName).to(byteValue);\n        }\n        break;","sourceCodeStart":178,"sourceCodeEnd":214,"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#L178-L214","documentation":"MutationUtils.setBeamValueToKey() also validates the field's TypeName in its switch; any TypeName not among the key-supported cases reaches the default branch and throws IllegalArgumentException('Unsupported field type: %s'). This is the same guard as the logical-type check but at the Beam FieldType level.","triggerScenarios":"A Beam Row key field has a TypeName not supported for Spanner keys (e.g. ROW, ARRAY, MAP, ITERABLE) when createKeyFromBeamRow builds the key.","commonSituations":"Nested Beam schemas used as key fields; mapping a composite/struct source key straight to the Spanner primary key; schema inference producing ROW-typed fields.","solutions":["Restrict key fields to scalar Beam FieldTypes (STRING, INT64, FLOAT64, BOOLEAN, DATETIME, BYTES).","Extract scalar components from nested rows and use those as the key.","Check the reported TypeName in the message and adjust the Beam schema accordingly."],"exampleFix":"// before\nFieldType keyType = FieldType.row(nestedSchema) // ROW not supported\n// after\nFieldType keyType = FieldType.STRING","handlingStrategy":"type-guard","validationCode":"TypeName tn = field.getType().getTypeName();\nif (tn.isCompositeType() || tn.isCollectionType()) throw new IllegalArgumentException(\"non-scalar key field: \" + field.getName());","typeGuard":"boolean isScalarTypeName(TypeName tn) { return !tn.isCompositeType() && !tn.isCollectionType() && !tn.isMapType(); }","tryCatchPattern":"try { keyBuilder = setBeamValueToKey(keyBuilder, field, row); } catch (IllegalArgumentException e) { /* use scalar component instead */ }","preventionTips":["Keep key fields to STRING/INT64/FLOAT64/BOOLEAN/DATETIME/BYTES FieldTypes","Extract fields from nested ROWs before key construction","Document key field requirements in pipeline config validation"],"tags":["java","apache-beam","spanner","schema"],"backgroundTag":"type-mismatch","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"}