apache/cassandra · error · IllegalStateException

There are multiple appenders of class

Error message

There are multiple appenders of class %s of names %s. There is only one appender of such class allowed.

What it means

At startup Cassandra checks the logback configuration and enforces that at most one appender of each virtual-table-enabled appender class exists; a second appender of the same class would make the vtable (system_logs / system_sessions) ambiguous. It throws IllegalStateException naming the class and the duplicate appender names.

Solutions

  1. Edit conf/logback.xml and remove or merge one of the duplicate appenders of that class so only one remains.
  2. Give the second output a different appender class (e.g. FILE vs the vtable appender class) instead of a second instance of the same class.
  3. Check overridden logback files (logback-test.xml, custom -Dlogback.configurationFile) that may add the same appender again.

Example fix

// before (logback.xml)
<appender name="DEBUGLOG" class="org.apache.cassandra.utils.logging.VirtualTableAppender">...</appender>
<appender name="DEBUGLOG2" class="org.apache.cassandra.utils.logging.VirtualTableAppender">...</appender>
// after
<appender name="DEBUGLOG" class="org.apache.cassandra.utils.logging.VirtualTableAppender">...</appender>
Defensive patterns

Strategy: validation

Validate before calling

// in logback.xml: grep for duplicate appender class definitions before startup
// ensure at most one <appender class="...VirtualTableAppender"> element exists

Prevention

When it happens

Trigger: logback.xml defines two <appender> elements whose class is the same virtual-table-enabled appender class (e.g. two instances of VirtualTableAppender / fixed-schema appender attached to different or the same loggers).

Common situations: Editing logback.xml to add a file appender while keeping an existing appender of the same class; merging config snippets during upgrades; operator copies of logback.xml that duplicate appenders for different log levels.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/utils/logging/LogbackLoggingSupport.java:186

    {
        int count = 0;
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        List<String> virtualAppenderNames = new ArrayList<>();
        for (Logger logBackLogger : lc.getLoggerList())
        {
            for (Iterator<Appender<ILoggingEvent>> iterator = logBackLogger.iteratorForAppenders(); iterator.hasNext();)
            {
                Appender<?> appender = iterator.next();
                if (appenderClass.isAssignableFrom(appender.getClass()))
                {
                    virtualAppenderNames.add(appender.getName());
                    count += 1;
                }
            }
        }

        if (count > 1)
            throw new IllegalStateException(String.format("There are multiple appenders of class %s of names %s. There is only one appender of such class allowed.",
                                                          appenderClass.getName(), String.join(",", virtualAppenderNames)));
    }

    private boolean hasAppenders(Logger logBackLogger)
    {
        Iterator<Appender<ILoggingEvent>> it = logBackLogger.iteratorForAppenders();
        return it.hasNext();
    }

    /**
     * The purpose of this class is to prevent logback from checking for config file change,
     * if the current thread is executing a sandboxed thread to avoid {@link AccessControlException}s.
     *
     * This is obsolete with logback versions that replaced {@link ReconfigureOnChangeFilter}
     * with {@link ch.qos.logback.classic.joran.ReconfigureOnChangeTask} (at least logback since 1.2.3).
     */
    private static class SMAwareReconfigureOnChangeFilter extends ReconfigureOnChangeFilter
    {

View on GitHub (pinned to 88fd0f6a0e)