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
- Stop the existing BinLog first (nodetool disablefullquerylog / disableauditlog, or call stop() on the existing instance) before rebuilding.
- Use a different log directory path for the new BinLog.
- If a previous instance crashed and leaked the path registration, restart the node so the static set is cleared.
- 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
- Always pair enablefullquerylog with disablefullquerylog before reconfiguring.
- Use distinct directories for FQL and audit logs.
- Track BinLog lifecycle centrally rather than rebuilding ad hoc.
- On startup failures, stop() the partially built BinLog so currentPaths is released.
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
- The log level was not changed, because you are using an…
- There are multiple appenders of class
- You are using Cassandra with an unsupported deployment. The…
- a hints file cannot be configured for both compression and…
- A maximum number of tokens per node is supported
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)