{"record":{"id":"0cb0122a9e2ca1d8","repo":"apache/beam","slug":"expected-the-managedtransform-schema-to-include-a-field","errorCode":null,"errorMessage":"Expected the ManagedTransform schema to include a field named 'transform_identifier' but received ${configRow}","messagePattern":"Expected the ManagedTransform schema to include a field named 'transform_identifier' but received (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/TransformProvider.java","lineNumber":151,"sourceCode":"        .equals(spec.getUrn())) {\n      ExternalTransforms.SchemaTransformPayload payload;\n      try {\n        payload = ExternalTransforms.SchemaTransformPayload.parseFrom(spec.getPayload());\n        if (PTransformTranslation.MANAGED_TRANSFORM_URN.equals(payload.getIdentifier())) {\n          try {\n            // ManagedSchemaTransform includes a schema field transform_identifier that includes the\n            // underlying schema\n            // transform ID so we special case that here.\n            Row configRow =\n                RowCoder.of(SchemaTranslation.schemaFromProto(payload.getConfigurationSchema()))\n                    .decode(new ByteArrayInputStream(payload.getConfigurationRow().toByteArray()));\n\n            for (String field : configRow.getSchema().getFieldNames()) {\n              if (field.equals(\"transform_identifier\")) {\n                return configRow.getValue(field);\n              }\n            }\n            throw new RuntimeException(\n                \"Expected the ManagedTransform schema to include a field named \"\n                    + \"'transform_identifier' but received \"\n                    + configRow);\n          } catch (IOException e) {\n            throw new RuntimeException(e);\n          }\n        } else {\n          return payload.getIdentifier();\n        }\n      } catch (InvalidProtocolBufferException e) {\n        throw new IllegalArgumentException(\n            \"Invalid payload type for URN \"\n                + BeamUrns.getUrn(ExternalTransforms.ExpansionMethods.Enum.SCHEMA_TRANSFORM),\n            e);\n      }\n    }\n    return spec.getUrn();\n  }","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/TransformProvider.java#L133-L169","documentation":"getTransformUniqueID expects the Managed transform's config Row schema to include a field named 'transform_identifier' which uniquely identifies the underlying transform; if absent it throws a RuntimeException including the received configRow.","triggerScenarios":"Submitting a managed-transform request whose config Row schema omits 'transform_identifier' or names it differently; config built by an incompatible Managed schema version.","commonSituations":"Beam version skew between client and expansion service; hand-built config Rows; YAML configs missing the identifier key.","solutions":["Include a 'transform_identifier' field in the ManagedTransform config schema and set its value.","Align client Beam SDK version with the expansion service's expected Managed schema.","Print configRow.getSchema().getFieldNames() (included in the message) to see actual fields.","Regenerate the config via the current Managed Transform API instead of hand-built Rows."],"exampleFix":"// before\nSchema configSchema = Schema.of(Field.of(\"provider\", Schema.FieldType.STRING));\n// after\nSchema configSchema = Schema.of(\n    Field.of(\"provider\", Schema.FieldType.STRING),\n    Field.of(\"transform_identifier\", Schema.FieldType.STRING));","handlingStrategy":"validation","validationCode":"Row configRow = decode(payload);\nif (!configRow.getSchema().getFieldNames().contains(\"transform_identifier\"))\n  throw new IllegalArgumentException(\"Config missing transform_identifier\");","typeGuard":"Optional<Object> transformId(Row row) { return row.getSchema().getFieldNames().contains(\"transform_identifier\") ? Optional.ofNullable(row.getValue(\"transform_identifier\")) : Optional.empty(); }","tryCatchPattern":"try { String id = provider.getTransformUniqueID(payload); } catch (RuntimeException e) { log.error(\"Managed config invalid: {}\", e.getMessage()); throw new ManagedConfigException(e); }","preventionTips":["Build Managed configs with the SDK API, not hand-built Rows","Check Managed schema docs for required fields per Beam version","Version-check client and service SDKs","Print configRow schema in pre-flight checks"],"tags":["beam","managed-transform","schema"],"backgroundTag":"missing-required-config-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}