{"record":{"id":"077a929d0ae5d200","repo":"xai-org/x-algorithm","slug":"class-has-to-be-either-a-tbase-or-thriftstruct-s","errorCode":null,"errorMessage":"class has to be either a TBase or ThriftStruct: %s.","messagePattern":"class has to be either a TBase or ThriftStruct: (.+?)\\.","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/compiler/types/TypeCompiler.java","lineNumber":109,"sourceCode":"  }\n\n  public static Type getTypeFromClassName(String className) throws SemanticCheckFailure {\n\n    Class<?> clazz;\n    try {\n      clazz = ClassCache.forName(className);\n    } catch (Exception e) {\n      throw new SemanticCheckFailure(\n          String.format(\"cannot find class %s\", className)\n      );\n    }\n\n    if (TBase.class.isAssignableFrom(clazz)) {\n      return Type.thriftOf((Class<? extends TBase>) clazz);\n    } else if (ThriftStruct.class.isAssignableFrom(clazz)) {\n      return Type.thriftStructOf((Class<? extends ThriftStruct>) clazz);\n    } else {\n      throw new SemanticCheckFailure(\n          String.format(\"class has to be either a TBase or ThriftStruct: %s.\", className)\n      );\n    }\n  }\n}\n","sourceCodeStart":91,"sourceCodeEnd":115,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/compiler/types/TypeCompiler.java#L91-L115","documentation":"After successfully loading the named class, getTypeFromClassName only accepts classes implementing TBase (apache-thrift) or ThriftStruct (scrooge). Anything else throws SemanticCheckFailure.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nType t = TypeCompiler.getTypeFromClassName(\"com.acme.model.UserPojo\");\n// after\nType t = TypeCompiler.getTypeFromClassName(\"com.acme.thriftscala.User\");","handlingStrategy":"type-guard","validationCode":"Class<?> c = ClassCache.forName(className);\nif (!TBase.class.isAssignableFrom(c) && !ThriftStruct.class.isAssignableFrom(c)) {\n  throw new IllegalArgumentException(\"not a thrift struct class\");\n}","typeGuard":"boolean isThriftStructClass(Class<?> c) {\n  return TBase.class.isAssignableFrom(c) || ThriftStruct.class.isAssignableFrom(c);\n}","tryCatchPattern":"catch SemanticCheckFailure 'class has to be either a TBase or ThriftStruct'; tell the caller to use a thrift-generated class","preventionTips":["Only reference codegen'd thrift structs from rules","Keep a curated registry of allowed struct classes"],"tags":["thrift","type-system","api-misuse"],"backgroundTag":"unsupported-class-type","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}