xai-org/x-algorithm · error · SemanticCheckFailure

Failed to create serializer for ThriftStruct %s: %s

Error message

Failed to create serializer for ThriftStruct %s: %s

What it means

thriftStructOf wraps its reflective construction of a scrooge-struct serializer in try/catch; any exception while reflecting over the class (finding companion apply/unapply methods, fields, annotations) is rethrown as SemanticCheckFailure with the class name and the original exception's toString. It signals that the compiler could not build a serializer for the named ThriftStruct, and the cause string is the key diagnostic.

Source

Thrown at botmaker/src/java/com/twitter/botmaker/compiler/Serializer.java:1626

        @Override
        protected T deserialize(TProtocol prot) throws TException {
          return (T) codec.decode(prot);
        }

        @Override
        protected void toScript(GenScript script, T value) {
          script.builder.append("NULL");
        }

        @Override
        protected void toStratoJson(GenScript script, T value) {
          throw new IllegalArgumentException(
              "Thriftscala objects are not supported in strato JSON");
        }
      };
    } catch (Exception e) {
      throw new SemanticCheckFailure(
          String.format("Failed to create serializer for ThriftStruct %s: %s",
              clazz.getName(), e.toString())
      );
    }
  }

  private static final class TByteBufferTransport extends TTransport {
    private ByteBuffer buffer;

    public TByteBufferTransport(ByteBuffer buf) {
      this.buffer = buf;
    }

    @Override
    public void close() {
    }

    @Override

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Read the %s cause in the message (the wrapped exception's toString) — NoClassDefFoundError/NoSuchMethodException points to version skew, IllegalAccess points to visibility.
  2. Align the scrooge/thrift codegen version that produced clazz with the version this compiler expects, and rebuild the structs.
  3. Verify the class actually is a scrooge-generated ThriftStruct with a usable companion object (not a hand-written implementation).
  4. Check for duplicate/shaded copies of the struct class on the classpath (dependency:tree / classpath:dump) and exclude the stale one.

Example fix

// before
Serializer.thriftStructOf(clazz); // Failed to create serializer for ThriftStruct com.example.MyStruct: java.lang.NoSuchMethodException

// after
// regenerate structs with matching scrooge version, then:
Preconditions.checkArgument(isScroogeGenerated(clazz), "not a scrooge struct: %s", clazz);
Serializer.thriftStructOf(clazz);
Defensive patterns

Strategy: try-catch

Validate before calling

try {
  Object companion = clazz.getMethod("companion").invoke(null); // smoke-check scrooge shape
} catch (ReflectiveOperationException ex) {
  throw new IllegalArgumentException(clazz + " is not scrooge-generated", ex);
}

Type guard

static boolean isScroogeStruct(Class<?> c) {
  return ThriftStruct.class.isAssignableFrom(c)
      && hasCompanionApply(c);
}

Try / catch

catch (SemanticCheckFailure e) {
  log.error("serializer init failed for {}: {}", className, e.getMessage());
  failRuleCompilationWithDiagnostics(e); // surface as user-facing rule error
}

Prevention

When it happens

Trigger: Calling Serializer.thriftStructOf(clazz) where clazz lacks the expected scrooge structure: missing companion object, inaccessible fields, classpath mismatch between thriftscala versions, or LinkageError/ClassNotFoundException during reflection.

Common situations: Thrift codegen version drift (scrooge version X structs inspected by a compiler expecting version Y); shaded/duplicate classes on the classpath; structs generated with different scrooge options; proguard/obfuscation stripping companion methods; passing a non-scrooge class that merely implements ThriftStruct.

Related errors


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