apache/cassandra · error · IllegalStateException

Already logging to

Error message

Already logging to 

What it means

BinLog (the Chronicle-Queue-backed binary log used for full query logging / audit logging) refuses to build a second BinLog targeting the same directory path. The static `currentPaths` set tracks every active log path across all BinLog instances; if the path is already registered, `build()` throws IllegalStateException. This prevents two writers corrupting the same chronicle queue directory.

Solutions

  1. Stop the existing BinLog first (nodetool disablefullquerylog / disableauditlog, or call stop() on the existing instance) before rebuilding.
  2. Use a different log directory path for the new BinLog.
  3. If a previous instance crashed and leaked the path registration, restart the node so the static set is cleared.
  4. Inspect fullquerylog/audit log config in cassandra.yaml and ensure only one subsystem owns the directory.

Example fix

// before
// FQL enabled while already running on same path
binLogBuilder.build(true); // throws IllegalStateException: Already logging to ...
// after
if (BinLog.isRunning()) // stop existing logger first
    BinLog.instance().stop();
binLogBuilder.build(true);
Defensive patterns

Strategy: try-catch

Validate before calling

// before building
Path p = Paths.get(fqlDir);
boolean active = BinLog.isRunning(); // or track instances yourself
if (active && p.toAbsolutePath().equals(activePath)) throw new IllegalStateException("FQL already running on " + p);

Try / catch

try { builder.build(true); } catch (IllegalStateException e) { logger.warn("BinLog already active: {}", e.getMessage()); /* stop existing instance and retry, or use different path */ }

Prevention

When it happens

Trigger: Calling BinLog.Builder.build() (e.g. re-enabling full query logging or audit logging via JMX/nodetool `enablefullquerylog`) while another BinLog instance is already active on the same path, or after a previous instance failed to release the path (the path is removed from currentPaths only when the BinLog is stopped).

Common situations: Enabling FQL twice without stopping it first; enabling FQL and audit logging pointed at the same directory; a leaked BinLog from a failed startup keeping the path registered; configuration reload that rebuilds the logger without calling stop().

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/utils/binlog/BinLog.java:449

        {
            this.maxArchiveRetries = maxArchiveRetries;
            return this;
        }

        public Builder blocking(boolean blocking)
        {
            this.blocking = blocking;
            return this;
        }


        public BinLog build(boolean cleanDirectory)
        {
            logger.info("Attempting to configure bin log: Path: {} Roll cycle: {} Blocking: {} Max queue weight: {} Max log size:{} Archive command: {}", path, rollCycle, blocking, maxQueueWeight, maxLogSize, archiveCommand);
            synchronized (currentPaths)
            {
                if (currentPaths.contains(path))
                    throw new IllegalStateException("Already logging to " + path);
                currentPaths.add(path);
            }
            try
            {
                Throwable sanitationThrowable = cleanEmptyLogFiles(new File(path), null);
                if (sanitationThrowable != null)
                    throw new RuntimeException(format("Unable to clean up %s directory from empty %s files.",
                                                      path.toAbsolutePath(), SingleChronicleQueue.SUFFIX),
                                               sanitationThrowable);

                // create the archiver before cleaning directories - ExternalArchiver will try to archive any existing file.
                BinLogArchiver archiver = Strings.isNullOrEmpty(archiveCommand) ? new DeletingArchiver(maxLogSize) : new ExternalArchiver(archiveCommand, path, maxArchiveRetries);
                if (cleanDirectory)
                {
                    logger.info("Cleaning directory: {} as requested", path);
                    if (new File(path).exists())
                    {
                        Throwable error = cleanDirectory(new File(path), null);

View on GitHub (pinned to 88fd0f6a0e)