apache/cassandra · warning · RuntimeException

Sampling already in progress

Error message

Sampling already in progress

What it means

MaxSampler tracks top-K maximum values per sampling window. Its beginSampling is synchronized and throws a RuntimeException if a sampling session is already active (isActive() true because a prior beginSampling's end time has not elapsed). Only one sampling session may run at a time.

Solutions

  1. Wait until the active sampling window (durationMillis of the prior call) expires
  2. Stop/finish the current sampling session before starting a new one
  3. Serialize sampling requests so only one beginSampling runs at a time
  4. Catch the RuntimeException and schedule a retry after the window ends

Example fix

// before
maxSampler.beginSampling(256, 5000);
maxSampler.beginSampling(256, 5000); // throws

// after
if (!maxSampler.isActive())
    maxSampler.beginSampling(256, 5000);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!maxSampler.isActive())
    maxSampler.beginSampling(capacity, durationMillis);

Type guard

function canBeginSampling(sampler) { return !sampler.isActive(); }

Try / catch

try { maxSampler.beginSampling(capacity, durationMillis); }
catch (RuntimeException e) { logger.info("Max sampling already active; skipping"); }

Prevention

When it happens

Trigger: Calling beginSampling (e.g. via JMX sampling of read/write latencies per partition) while another sampling session started earlier is still active and its end time has not passed.

Common situations: Running two sampling requests concurrently via JMX or nodetool; monitoring automation overlapping sampling windows; long durationMillis on the first call still in effect when a second call arrives.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/metrics/MaxSampler.java:43

import com.google.common.collect.MinMaxPriorityQueue;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

/**
 * Note: {@link Sampler#samplerExecutor} is single threaded but we still need to synchronize as we have access
 * from both internal and the external JMX context that can cause races.
 */
public abstract class MaxSampler<T> extends Sampler<T>
{
    private int capacity;
    private MinMaxPriorityQueue<Sample<T>> queue;
    private final Comparator<Sample<T>> comp = Collections.reverseOrder(Comparator.comparing(p -> p.count));

    @Override
    public synchronized void beginSampling(int capacity, long durationMillis)
    {
        if (isActive())
            throw new RuntimeException("Sampling already in progress");
        updateEndTime(clock.now() + MILLISECONDS.toNanos(durationMillis));
        queue = MinMaxPriorityQueue.orderedBy(comp)
                                   .maximumSize(Math.max(1, capacity))
                                   .create();
        this.capacity = capacity;
    }

    @Override
    public synchronized List<Sample<T>> finishSampling(int count)
    {
        List<Sample<T>> result = new ArrayList<>(count);
        if (isEnabled())
        {
            disable();
            Sample<T> next;
            while ((next = queue.poll()) != null && result.size() <= count)
                result.add(next);
        }

View on GitHub (pinned to 88fd0f6a0e)