apache/beam · error · IllegalArgumentException

Expected thrift class but got

Error message

Expected thrift class but got: %s

What it means

ThriftSchema.schemaFor builds a Beam Schema from a thrift class but first requires the target class to implement TBase. If a non-thrift class is passed, an IllegalArgumentException with this message is thrown.

Solutions

  1. Pass a class generated by the thrift compiler (extends TBase), e.g. com.example.thrift.ThriftRecord
  2. Check the generic/raw type being forwarded — schemaFor(getRawType()) may be receiving Object or a wrapper
  3. If the element type should be a POJO, use the standard Schema inference instead of ThriftSchema

Example fix

// before
Schema s = ThriftSchema.provider().schemaFor(TypeDescriptor.of(MyPojo.class)); // not TBase
// after
Schema s = ThriftSchema.provider().schemaFor(TypeDescriptor.of(com.example.thrift.ThriftRecord.class));
Defensive patterns

Strategy: type-guard

Validate before calling

if (!TBase.class.isAssignableFrom(ThriftRecord.class)) { throw new IllegalArgumentException("element type must be a thrift-generated TBase"); }

Type guard

static <T> boolean isThriftType(Class<T> c) { return TBase.class.isAssignableFrom(c); }

Try / catch

try { schema = ThriftSchema.provider().schemaFor(td); } catch (IllegalArgumentException e) { throw new IllegalStateException("Pass a thrift-generated class, not " + td.getRawType(), e); }

Prevention

When it happens

Trigger: Passing a TypeDescriptor or Class that is not a generated thrift struct (e.g. a plain POJO or the wrong type parameter) to ThriftSchema.provider().schemaFor(...) or a ThriftIO transform expecting a thrift class.

Common situations: Refactoring pipeline types and accidentally wiring a POJO where a generated thrift struct belongs; using the raw generic type instead of the concrete TBase subclass.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/328a7acfeb8499fc. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/thrift/src/main/java/org/apache/beam/sdk/io/thrift/ThriftSchema.java:173

    }

    public @NonNull SchemaProvider provider() {
      if (typedefs.isEmpty()) {
        return defaultProvider;
      } else {
        return new ThriftSchema(unmodifiableMap(new HashMap<>(typedefs)));
      }
    }
  }

  @Override
  public <T> @NonNull Schema schemaFor(TypeDescriptor<T> typeDescriptor) {
    return schemaFor(typeDescriptor.getRawType());
  }

  private Schema schemaFor(Class<?> targetClass) {
    if (!TBase.class.isAssignableFrom(targetClass)) {
      throw new IllegalArgumentException("Expected thrift class but got: " + targetClass);
    }
    final Stream<Schema.Field> fields =
        thriftFieldDescriptors(targetClass).values().stream().map(this::beamField);
    if (TUnion.class.isAssignableFrom(targetClass)) {
      // Beam OneOf is just a record of fields where exactly one must be non-null, so it doesn't
      // allow the types of the cases to be nullable
      return OneOfType.create(fields.map(f -> f.withNullable(false)).collect(Collectors.toList()))
          .getOneOfSchema();
    } else {
      return fields
          .reduce(Schema.builder(), Schema.Builder::addField, ThriftSchema::throwingCombiner)
          .build();
    }
  }

  private static <X> X throwingCombiner(X lhs, X rhs) {
    throw new IllegalStateException();
  }

View on GitHub (pinned to 12126d8942)