xai-org/x-algorithm · error · SemanticCheckFailure
class has to be either a TBase or ThriftStruct: %s.
Error message
class has to be either a TBase or ThriftStruct: %s.
What it means
After successfully loading the named class, getTypeFromClassName only accepts classes implementing TBase (apache-thrift) or ThriftStruct (scrooge). Anything else throws SemanticCheckFailure.
Source
Thrown at botmaker/src/java/com/twitter/botmaker/compiler/types/TypeCompiler.java:109
}
public static Type getTypeFromClassName(String className) throws SemanticCheckFailure {
Class<?> clazz;
try {
clazz = ClassCache.forName(className);
} catch (Exception e) {
throw new SemanticCheckFailure(
String.format("cannot find class %s", className)
);
}
if (TBase.class.isAssignableFrom(clazz)) {
return Type.thriftOf((Class<? extends TBase>) clazz);
} else if (ThriftStruct.class.isAssignableFrom(clazz)) {
return Type.thriftStructOf((Class<? extends ThriftStruct>) clazz);
} else {
throw new SemanticCheckFailure(
String.format("class has to be either a TBase or ThriftStruct: %s.", className)
);
}
}
}
View on GitHub (pinned to 24c60942c5)
Solutions
- Reference a thrift-generated struct class (TBase or ThriftStruct) instead
- Generate the class with scrooge/apache-thrift codegen so it implements the required interface
- Define a thrift IDL for the type and use its generated class
Example fix
// before
Type t = TypeCompiler.getTypeFromClassName("com.acme.model.UserPojo");
// after
Type t = TypeCompiler.getTypeFromClassName("com.acme.thriftscala.User"); Defensive patterns
Strategy: type-guard
Validate before calling
Class<?> c = ClassCache.forName(className);
if (!TBase.class.isAssignableFrom(c) && !ThriftStruct.class.isAssignableFrom(c)) {
throw new IllegalArgumentException("not a thrift struct class");
} Type guard
boolean isThriftStructClass(Class<?> c) {
return TBase.class.isAssignableFrom(c) || ThriftStruct.class.isAssignableFrom(c);
} Try / catch
catch SemanticCheckFailure 'class has to be either a TBase or ThriftStruct'; tell the caller to use a thrift-generated class
Prevention
- Only reference codegen'd thrift structs from rules
- Keep a curated registry of allowed struct classes
When it happens
Trigger: Passing a valid but non-thrift class name — e.g. java.util.HashMap, a POJO, or an interface — to getTypeFromClassName, typically via a rule's type annotation.
Common situations: Rules referencing Java domain classes instead of thrift-generated structs; classes generated by a different thrift generator (e.g. finagle/other) that implements neither interface.
Related errors
- Unsupported field type %s
- Unsupported field type %s
- Unsupported field type %s
- Cannot create StructTuple Type without a fieldName list.
- class to be imported has to be either a TBase or ThriftStruc
AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28).
Data as JSON: /api/errors/077a929d0ae5d200.
Report an issue: GitHub.