{"record":{"id":"87b2edd63374e5f3","repo":"apache/beam","slug":"given-message-schema-s-ndoes-not-match-schema-inferred-from-87b2ed","errorCode":null,"errorMessage":"Given message schema: '%s'%ndoes not match schema inferred from thrift class.%nThrift class: '%s'%nInferred schema: '%s'","messagePattern":"Given message schema: '(.+?)'%ndoes not match schema inferred from thrift class\\.%nThrift class: '(.+?)'%nInferred schema: '(.+?)'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/thrift/src/main/java/org/apache/beam/sdk/io/thrift/ThriftPayloadSerializerProvider.java","lineNumber":72,"sourceCode":"  }\n\n  private static TProtocolFactory getProtocolFactory(Map<String, Object> tableParams) {\n    String thriftFactoryClassName =\n        checkArgumentNotNull(tableParams.get(\"thriftProtocolFactoryClass\")).toString();\n    try {\n      Class<?> thriftClass = Class.forName(thriftFactoryClassName);\n      return thriftClass.asSubclass(TProtocolFactory.class).getDeclaredConstructor().newInstance();\n    } catch (ReflectiveOperationException e) {\n      throw new IllegalArgumentException(\n          \"Incorrect thrift protocol factory class provided: \" + thriftFactoryClassName, e);\n    }\n  }\n\n  private static void inferAndVerifySchema(Class<?> thriftClass, Schema requiredSchema) {\n    TypeDescriptor<?> typeDescriptor = TypeDescriptor.of(thriftClass);\n    Schema schema = checkArgumentNotNull(ThriftSchema.provider().schemaFor(typeDescriptor));\n    if (!schema.assignableTo(requiredSchema)) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Given message schema: '%s'%n\"\n                  + \"does not match schema inferred from thrift class.%n\"\n                  + \"Thrift class: '%s'%n\"\n                  + \"Inferred schema: '%s'\",\n              requiredSchema, thriftClass.getName(), schema));\n    }\n  }\n\n  /** A helper needed to fix the type `T` of thriftClass to satisfy RowMessages constraints. */\n  private static <T extends TBase> PayloadSerializer getPayloadSerializer(\n      Schema schema, TProtocolFactory protocolFactory, Class<T> thriftClass) {\n    Coder<T> coder = ThriftCoder.of(thriftClass, protocolFactory);\n    TypeDescriptor<T> descriptor = TypeDescriptor.of(thriftClass);\n    SimpleFunction<byte[], Row> toRowFn =\n        RowMessages.bytesToRowFn(ThriftSchema.provider(), descriptor, coder);\n    return PayloadSerializer.of(\n        RowMessages.rowToBytesFn(ThriftSchema.provider(), descriptor, coder),","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/thrift/src/main/java/org/apache/beam/sdk/io/thrift/ThriftPayloadSerializerProvider.java#L54-L90","documentation":"inferAndVerifySchema derives a Beam Schema from the thrift class and checks that the user-provided target schema is assignable to it. When the provided schema does not match the schema inferred from the thrift class, an IllegalArgumentException with this formatted message (showing both schemas and the class) is thrown.","triggerScenarios":"Calling ThriftIO write/read with an explicitly supplied Beam Schema whose field names, types, nullability, or ordering don't match what ThriftSchema infers from the configured thrift class.","commonSituations":"Hand-writing a Beam Schema for a thrift type instead of deriving it; thrift IDL updated (field added/renamed) but the supplied schema not updated; nullable/optional mismatch between thrift requirement and Beam field nullability.","solutions":["Compare the 'Inferred schema' in the message with your provided schema and align field names, types, and nullability","Regenerate thrift classes after IDL changes and re-derive the schema instead of maintaining it by hand","Use the schema inferred from the thrift class (ThriftSchema.provider().schemaFor(TypeDescriptor.of(cls))) rather than a hand-built one"],"exampleFix":"// before\nSchema mySchema = Schema.of(Field.of(\"name\", FieldType.STRING), Field.of(\"age\", FieldType.INT32));\nthriftIO.withSchema(mySchema); // mismatches inferred schema\n// after\nSchema inferred = ThriftSchema.provider()\n    .schemaFor(TypeDescriptor.of(ThriftRecord.class));\nthriftIO.withSchema(inferred);","handlingStrategy":"validation","validationCode":"Schema inferred = ThriftSchema.provider().schemaFor(TypeDescriptor.of(ThriftRecord.class)); if (!inferred.equals(provided)) { throw new IllegalArgumentException(\"provided schema differs from inferred thrift schema\"); }","typeGuard":null,"tryCatchPattern":"try { thriftIO.withSchema(mySchema); } catch (IllegalArgumentException e) { schema = ThriftSchema.provider().schemaFor(TypeDescriptor.of(ThriftRecord.class)); }","preventionTips":["Derive schemas from the thrift class instead of hand-writing them","Re-derive schemas in CI whenever the .thrift file changes","Check the message's Inferred schema output for the exact expected shape"],"tags":["java","thrift","schema","validation"],"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-20T03:17:13.778Z"}