apache/cassandra · warning

<garbage collection summary>

Error message

<garbage collection summary>

What it means

A WARN/INFO/TRACE log (not an exception) from GCInspector.handleNotification for a GarbageCollectionNotificationInfo whose GC is a concurrent phase (e.g. G1 concurrent mark/cleanup). The '<garbage collection summary>' string is the formatted GC statistics built into sb. It is logged at WARN when the duration exceeds the concurrent-phase warn threshold (gc_concurrent_phase_warn_threshold_in_ms), INFO above the log threshold, TRACE otherwise, and additionally dumps a StatusLogger status when the duration exceeds the concurrent status threshold (default 200ms).

Solutions

  1. Inspect the log line and StatusLogger output to identify which concurrent phase is slow and the heap usage before/after
  2. Tune GC via jvm11-server.options (e.g. increase heap, adjust G1 heap region size, InitiatingHeapOccupancyPercent, GC threads) or via -Dcassandra.gc_concurrent_phase_warn_threshold_ms if thresholds are too aggressive
  3. If pauses cause coordinator timeouts, investigate memory pressure (huge partitions, memtable sizing) driving long concurrent cycles

Example fix

// before (jvm-server.options)
-Xms8G -Xmx8G

// after
-Xms31G -Xmx31G  # reduce concurrent-cycle frequency on large nodes
// or relax threshold:
-Dcassandra.gc_concurrent_phase_warn_threshold_ms=1000
Defensive patterns

Strategy: validation

Validate before calling

// Threshold sanity check before deploy (gc_concurrent_phase_warn_threshold_in_ms)
long warnMs = Long.getLong("cassandra.gc_concurrent_phase_warn_threshold_ms", 500);
if (warnMs <= 0) System.out.println("Concurrent-phase GC warning disabled; long concurrent cycles will be silent");

Prevention

When it happens

Trigger: JVM GC bean notification for a concurrent collection phase whose duration exceeds getGcConcurrentPhaseWarnThresholdInMs() (WARN), getGcConcurrentPhaseLogThresholdInMs() (INFO), or any duration with trace logging enabled; StatusLogger fires when duration > getConcurrentStatusThresholdInMs().

Common situations: Large heaps with G1/ZGC/CMS concurrent cycles taking hundreds of ms; undersized heap or too few GC threads; heavy write load causing long concurrent mark cycles; operators investigating latency spikes.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/service/GCInspector.java:331

                    sb.append(" -> ");
                    sb.append(after.getUsed());
                    if (!key.equals(gcState.keys[gcState.keys.length - 1]))
                        sb.append("; ");
                    bytes += before.getUsed() - after.getUsed();
                }
            }

            while (true)
            {
                State prev = state.get();
                if (state.compareAndSet(prev, new State(duration, bytes, prev)))
                    break;
            }

            if (isConcurrentPhase(info.getGcCause(), info.getGcName()))
            {
                if (getGcConcurrentPhaseWarnThresholdInMs() != 0 && duration > getGcConcurrentPhaseWarnThresholdInMs())
                    logger.warn(sb.toString());
                else if (duration > getGcConcurrentPhaseLogThresholdInMs())
                    logger.info(sb.toString());
                else if (logger.isTraceEnabled())
                    logger.trace(sb.toString());

                if (duration > this.getConcurrentStatusThresholdInMs())
                    StatusLogger.log();
            }
            else
            {
                if (getGcWarnThresholdInMs() != 0 && duration > getGcWarnThresholdInMs())
                    logger.warn(sb.toString());
                else if (duration > getGcLogThresholdInMs())
                    logger.info(sb.toString());
                else if (logger.isTraceEnabled())
                    logger.trace(sb.toString());

                if (duration > this.getStatusThresholdInMs())

View on GitHub (pinned to 88fd0f6a0e)