apache/cassandra · error · InvalidClassException

Event class must be of type DiagnosticEvent

Error message

Event class must be of type DiagnosticEvent

What it means

After loading a Cassandra-namespaced class, getEventClass verifies it extends DiagnosticEvent. If not, it throws InvalidClassException("Event class must be of type DiagnosticEvent") because diagnostic persistence can only store event objects deriving from DiagnosticEvent.

Solutions

  1. Pass a class that extends org.apache.cassandra.diag.DiagnosticEvent (see DiagnosticEventService registered events)
  2. Check with javap or IDE that the target class inherits from DiagnosticEvent
  3. Update the class name to the current one after Cassandra upgrades
  4. Use org.apache.cassandra.diag.DiagnosticEventService.getEventClasses() equivalents to enumerate valid events

Example fix

// before
bean.enableEventPersistence("org.apache.cassandra.diag.DiagnosticEventService");
// after
bean.enableEventPersistence("org.apache.cassandra.diag.DiagnosticEvent"); // must be a DiagnosticEvent subtype
bean.enableEventPersistence("org.apache.cassandra.db.commitlog.CommitLogEvent");
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> c = Class.forName(name, false, loader);
if (!DiagnosticEvent.class.isAssignableFrom(c))
    throw new IllegalArgumentException(name + " is not a DiagnosticEvent");

Type guard

boolean isDiagnosticEvent(String name) {
    try { return DiagnosticEvent.class.isAssignableFrom(Class.forName(name, false, loader)); }
    catch (ClassNotFoundException e) { return false; }
}

Try / catch

try {
    bean.enableEventPersistence(eventClazz);
} catch (InvalidClassException e) {
    // resolve to a class extending org.apache.cassandra.diag.DiagnosticEvent
}

Prevention

When it happens

Trigger: Calling enableEventPersistence/getEvents/disableEventPersistence with an eventClazz that resolves to a Cassandra class but not a DiagnosticEvent subclass (e.g. passing a service or config class).

Common situations: Passing DiagnosticEventService or a management class instead of a concrete event class; renamed/refactored event hierarchy after upgrade; copy-paste of class names from unrelated packages.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/8d97aa74505adb48. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/diag/DiagnosticEventPersistence.java:142

        Class<? extends DiagnosticEvent> cls = event.getClass();
        logger.trace("Persisting received {} event", cls.getName());
        DiagnosticEventStore<Long> store = getStore(cls);
        store.store(event);
        LastEventIdBroadcaster.instance().setLastEventId(event.getClass().getName(), store.getLastEventId());
    }

    @SuppressWarnings("unchecked")
    private Class<DiagnosticEvent> getEventClass(String eventClazz) throws ClassNotFoundException, InvalidClassException
    {
        // get class by eventClazz argument name
        // restrict class loading for security reasons
        if (!eventClazz.startsWith("org.apache.cassandra."))
            throw new RuntimeException("Not a Cassandra event class: " + eventClazz);

        Class<?> clazz = Class.forName(eventClazz, false, DiagnosticEventPersistence.class.getClassLoader());

        if (!(DiagnosticEvent.class.isAssignableFrom(clazz)))
            throw new InvalidClassException("Event class must be of type DiagnosticEvent");

        return (Class<DiagnosticEvent>) clazz.asSubclass(DiagnosticEvent.class);
    }

    private DiagnosticEventStore<Long> getStore(Class cls)
    {
        return stores.computeIfAbsent(cls, (storeKey) -> new DiagnosticEventMemoryStore());
    }
}

View on GitHub (pinned to 88fd0f6a0e)