{"record":{"id":"8739971838efd4ec","repo":"apache/beam","slug":"schema-in-expansion-request-payload-is-not-assignable-to-the","errorCode":null,"errorMessage":"Schema in expansion request payload is not assignable to the schema for the configuration object.%n%nPayload Schema: %s%n%nConfiguration Schema: %s","messagePattern":"Schema in expansion request payload is not assignable to the schema for the configuration object\\.%n%nPayload Schema: (.+?)%n%nConfiguration Schema: (.+?)","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java","lineNumber":477,"sourceCode":"            String.format(\n                \"Failed to construct instance of configuration class '%s'\",\n                configurationClass.getName()),\n            e);\n      }\n    }\n  }\n\n  private static <ConfigT> ConfigT payloadToConfigSchema(\n      ExternalConfigurationPayload payload, Class<ConfigT> configurationClass)\n      throws NoSuchSchemaException {\n    Schema configSchema = SCHEMA_REGISTRY.getSchema(configurationClass);\n    SerializableFunction<Row, ConfigT> fromRowFunc =\n        SCHEMA_REGISTRY.getFromRowFunction(configurationClass);\n\n    Row payloadRow = decodeConfigObjectRow(payload.getSchema(), payload.getPayload());\n\n    if (!payloadRow.getSchema().assignableTo(configSchema)) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Schema in expansion request payload is not assignable to the schema for the \"\n                  + \"configuration object.%n%nPayload Schema: %s%n%nConfiguration Schema: %s\",\n              payloadRow.getSchema(), configSchema));\n    }\n\n    return fromRowFunc.apply(payloadRow);\n  }\n\n  private static <ConfigT> ConfigT payloadToConfigSetters(\n      ExternalConfigurationPayload payload, Class<ConfigT> configurationClass)\n      throws ReflectiveOperationException {\n    Row configRow = decodeConfigObjectRow(payload.getSchema(), payload.getPayload());\n\n    Constructor<ConfigT> constructor = configurationClass.getDeclaredConstructor();\n    constructor.setAccessible(true);\n\n    ConfigT config = constructor.newInstance();","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/ExpansionService.java#L459-L495","documentation":"Thrown by ExpansionService.payloadToConfig when the schema carried in an expansion request's payload Row is not assignable to the schema computed for the target configuration class. The service decodes the payload bytes into a Row and requires its schema to be compatible with configSchema before mapping the Row onto the configuration object via setters. This protects the service from populating a configuration object from structurally incompatible data.","triggerScenarios":"Calling ExpansionService.expand (via the Beam expansion protocol) with a payload whose encoded Row schema differs from the schema derived from the configuration class — e.g. a client SDK of a different Beam version encoding fields with different names, types, or ordering than the server-side config class expects.","commonSituations":"Client and server Beam SDK version mismatch (schema evolution between releases); a custom transform whose config class changed after a client cached its expansion response; hand-crafted expansion requests built against an outdated schema.","solutions":["Upgrade the client SDK and the expansion service jar to the same Beam version so payload schemas match.","Regenerate/rebuild the expansion request against the current transform's configuration class schema.","Compare the 'Payload Schema' and 'Configuration Schema' printed in the message field-by-field to find the divergent field name/type and fix the payload construction code."],"exampleFix":"// before: client built payload with old schema (field 'regex' as STRING vs new field 'pattern')\n// after: pin client and service to matching versions and rebuild the payload Row\nRow configRow = Row.withSchema(configSchema).addValues(pattern).build();","handlingStrategy":"validation","validationCode":"Schema payloadSchema = Row.decode(...).getSchema(); // or payload.getSchema()\nSchema configSchema = SCHEMA_REGISTRY.getSchema(MyConfig.class);\nif (!payloadSchema.assignableTo(configSchema)) {\n  throw new IllegalStateException(\"Payload schema mismatch; sync client/server Beam versions\");\n}","typeGuard":"boolean schemasCompatible(Row row, Schema config) { return row != null && row.getSchema() != null && row.getSchema().assignableTo(config); }","tryCatchPattern":"try {\n  expansionResponse = service.expand(request);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"not assignable\")) { /* rebuild payload with current schema */ }\n  else throw e;\n}","preventionTips":["Pin client and expansion service to the same Beam version.","Rebuild expansion requests whenever the transform's config class changes.","Log and diff both schemas (message includes them) when upgrading."],"tags":["java","beam","schema","expansion-service"],"backgroundTag":"schema-validation-failed","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"}