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

  1. Reference a thrift-generated struct class (TBase or ThriftStruct) instead
  2. Generate the class with scrooge/apache-thrift codegen so it implements the required interface
  3. 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

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


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/077a929d0ae5d200. Report an issue: GitHub.