{"record":{"id":"06c91857295a8987","repo":"xai-org/x-algorithm","slug":"class-to-be-imported-has-to-be-either-a-tbase-or-t","errorCode":null,"errorMessage":"class to be imported has to be either a TBase or ThriftStruct: %s.","messagePattern":"class to be imported has to be either a TBase or ThriftStruct: (.+?)\\.","errorType":"validation","errorClass":"SemanticCheckFailure","httpStatus":null,"severity":"error","filePath":"botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java","lineNumber":710,"sourceCode":"    try {\n      ASTNode node = createASTNodeTree(context, child);\n      return ToThrift.mkNewThriftObject(exprText, className, node);\n    } catch (Exception e) {\n      throw new SemanticCheckFailure(e);\n    }\n  }\n\n  private ASTNode toImport(CompilerContext context, Tree root) throws SemanticCheckFailure {\n\n    String clsName = getFullName(root);\n    String alias = root.getChild(root.getChildCount() - 1).getText();\n    Type type = TypeCompiler.getTypeFromClassName(clsName);\n    if (type instanceof ThriftType) {\n      context.defineType((ThriftType) type, alias);\n    } else if (type instanceof ThriftStructType) {\n      context.defineType((ThriftStructType) type, alias);\n    } else {\n      throw new SemanticCheckFailure(\n          String.format(\n              \"class to be imported has to be either a TBase or ThriftStruct: %s.\", clsName)\n      );\n    }\n\n    return Constant.UNIT;\n  }\n\n  private ASTNode toImportAs(CompilerContext context, Tree root) throws SemanticCheckFailure {\n\n    String cls = getFullName(root, root.getChildCount() - 1);\n    String alias = root.getChild(root.getChildCount() - 1).getText();\n\n    Class<?> clazz;\n    try {\n      clazz = ClassCache.forName(cls);\n    } catch (Exception e) {\n      throw new SemanticCheckFailure(","sourceCodeStart":692,"sourceCodeEnd":728,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/botmaker/src/java/com/twitter/botmaker/compiler/Compiler.java#L692-L728","documentation":"The `import` statement in a Botmaker expression must reference a Thrift-generated type. TypeCompiler resolved the class, but it was neither a ThriftType (TBase) nor a ThriftStructType, so the compiler refuses to bind it into the type context.","triggerScenarios":"Using `import(\"com.example.SomeClass\", alias)` where SomeClass is a plain Java class, an interface, or a Thrift class generated by an incompatible codegen version.","commonSituations":"Trying to import java.lang or guava classes, importing a Thrift struct compiled against a mismatched thrift/scrooge runtime, or importing a class not on the compiler's classpath (which may resolve to a stub).","solutions":["Replace the imported class with a Thrift-generated TBase or ThriftStruct class","Regenerate the Thrift/Scrooge classes with the codegen version matching the Botmaker runtime","Verify the class is on the compile classpath and is the generated struct, not a hand-written wrapper"],"exampleFix":"// before\nimport(\"com.example.MyPlainPojo\", pojo)\n// after\nimport(\"com.example.thriftscala.MyThriftStruct\", myStruct)","handlingStrategy":"validation","validationCode":"Class<?> c = ClassCache.forName(clsName);\nif (!TBase.class.isAssignableFrom(c) && !ThriftStruct.class.isAssignableFrom(c))\n  throw new IllegalArgumentException(clsName + \" is not a Thrift type\");","typeGuard":"static boolean isImportableThriftType(Class<?> c) {\n  return TBase.class.isAssignableFrom(c) || ThriftStruct.class.isAssignableFrom(c);\n}","tryCatchPattern":"catch (SemanticCheckFailure e) { /* surface import name and fix config */ }","preventionTips":["Only import generated Thrift structs","Pin thrift codegen version to the runtime version"],"tags":["botmaker","import","thrift","type-check"],"backgroundTag":"unsupported-import-type","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}