apache/cassandra · error · java.lang.RuntimeException

Error occurred during repair

Error message

Error occurred during repair

What it means

Nodetool Repair wraps any exception thrown by the JMX repairAsync call in a RuntimeException 'Error occurred during repair'. The client-side argument parsing succeeded; the node rejected or failed while initiating the asynchronous repair session.

Solutions

  1. Check node logs for the real cause; look for concurrent-repair conflicts in `nodetool netstats`/tpstats
  2. Ensure no other repair session is running (wait or let it finish)
  3. Verify keyspace/table names
  4. Retry after topology settles; investigate range mismatch if it persists

Example fix

// before
nodetool repair nonexistent_ks
// after
nodetool repair existing_ks
Defensive patterns

Strategy: try-catch

Validate before calling

nodetool describecluster | grep -q "schema disagreement" && echo "fix schema first"

Try / catch

try { probe.repairAsync(out, ks, options); } catch (RuntimeException e) { log.error("repair failed to start: {}", e.getCause(), e); /* check for concurrent repair, then retry */ throw e; }

Prevention

When it happens

Trigger: `nodetool repair` when the node cannot start the repair: no common token ranges between nodes, another repair already running (adjacent command conflicts), unknown keyspace/table, or JMX IOException.

Common situations: Concurrent repairs colliding ('Two nodes... repair' / 'can not be merged' style node-side errors); typo'd keyspace; repairing after topology changes with out-of-sync range maps.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tools/nodetool/Repair.java:178

        List<String> keyspaces = parseOptionalKeyspaceNonLocal(args, probe);
        String[] cfnames = parseOptionalTables(args);

        if (primaryRange && (!specificDataCenters.isEmpty() || !specificHosts.isEmpty()))
            throw new RuntimeException("Primary range repair should be performed on all nodes in the cluster.");

        for (String keyspace : keyspaces)
        {
            // avoid repairing system_distributed by default (CASSANDRA-9621)
            if ((args == null || args.isEmpty()) && ONLY_EXPLICITLY_REPAIRED.contains(keyspace))
                continue;

            Map<String, String> options = createOptions(probe::getDataCenter, cfnames);
            try
            {
                probe.repairAsync(probe.output().out, keyspace, options);
            } catch (Exception e)
            {
                throw new RuntimeException("Error occurred during repair", e);
            }
        }
    }

    public Map<String, String> createOptions(Supplier<String> localDCOption, String[] cfnames)
    {
        Map<String, String> options = new HashMap<>();
        RepairParallelism parallelismDegree = RepairParallelism.PARALLEL;
        if (sequential)
            parallelismDegree = RepairParallelism.SEQUENTIAL;
        else if (dcParallel)
            parallelismDegree = RepairParallelism.DATACENTER_AWARE;
        options.put(RepairOption.PARALLELISM_KEY, parallelismDegree.getName());
        options.put(RepairOption.PRIMARY_RANGE_KEY, Boolean.toString(primaryRange));
        options.put(RepairOption.INCREMENTAL_KEY, Boolean.toString(!fullRepair && !(paxosOnly && getPreviewKind() == PreviewKind.NONE)));
        options.put(RepairOption.JOB_THREADS_KEY, Integer.toString(numJobThreads));
        options.put(RepairOption.TRACE_KEY, Boolean.toString(trace));
        options.put(RepairOption.COLUMNFAMILIES_KEY, StringUtils.join(cfnames, ","));

View on GitHub (pinned to 88fd0f6a0e)