apache/cassandra · error · IllegalArgumentException

the local data center must be part of the repair; requested

Error message

the local data center must be part of the repair; requested {options.getDataCenters()} but DC is {DatabaseDescriptor.getLocalDataCenter()}

What it means

createRepairTask validates that when a repair explicitly lists datacenters (-dc), the local node's datacenter must be among them; otherwise this node cannot coordinate a meaningful repair. Thrown as IllegalArgumentException before the RepairCoordinator is created.

Source

Thrown at src/java/org/apache/cassandra/service/StorageService.java:3222

        for (int i = start; i != end; i = (i+1) % tokens.size())
        {
            Range<Token> range = new Range<>(tokens.get(i), tokens.get((i+1) % tokens.size()));
            repairingRange.add(range);
        }

        return repairingRange;
    }

    public TokenFactory getTokenFactory()
    {
        return ClusterMetadata.current().partitioner.getTokenFactory();
    }

    private FutureTask<Object> createRepairTask(final int cmd, final String keyspace, final RepairOption options, List<ProgressListener> listeners)
    {
        if (!options.getDataCenters().isEmpty() && !options.getDataCenters().contains(DatabaseDescriptor.getLocalDataCenter()))
        {
            throw new IllegalArgumentException("the local data center must be part of the repair; requested " + options.getDataCenters() + " but DC is " + DatabaseDescriptor.getLocalDataCenter());
        }
        Set<String> existingDatacenters = ClusterMetadata.current().directory.allDatacenterEndpoints().keys().elementSet();
        List<String> datacenters = new ArrayList<>(options.getDataCenters());
        if (!existingDatacenters.containsAll(datacenters))
        {
            datacenters.removeAll(existingDatacenters);
            throw new IllegalArgumentException("data center(s) " + datacenters.toString() + " not found");
        }

        RepairCoordinator task = new RepairCoordinator(this, cmd, options, keyspace);
        task.addProgressListener(progressSupport);
        for (ProgressListener listener : listeners)
            task.addProgressListener(listener);

        if (options.isTraced())
            return new FutureTaskWithResources<>(() -> ExecutorLocals::clear, task);
        return new FutureTask<>(task);
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Run the repair from a node in one of the requested datacenters, or add the local DC to -dc
  2. Verify the node's DC via nodetool info / gossip and correct endpoint_snitch or cassandra-rackdc.properties if the local DC is wrong
  3. Include all target DCs, e.g. -dc dc1,dc2

Example fix

// before
nodetool repair -dc dc1 my_keyspace   # run on a dc2 node
// after
nodetool repair -dc dc1,dc2 my_keyspace
Defensive patterns

Strategy: validation

Validate before calling

String localDc = DatabaseDescriptor.getLocalDataCenter();
if (!options.getDataCenters().isEmpty() && !options.getDataCenters().contains(localDc))
    options.getDataCenters().add(localDc);

Try / catch

try { ss.repairAsync(ks, opt); } catch (IllegalArgumentException e) { /* rerun from a node in the requested DC or include local DC */ }

Prevention

When it happens

Trigger: Calling `nodetool repair -dc dc1 <keyspace>` from a node whose DatabaseDescriptor.getLocalDataCenter() is, say, dc2 — i.e., the requested DC set does not include the coordinator's own DC.

Common situations: Multi-DC clusters where an operator SSHes into the wrong DC's node; endpoint_snitch misconfiguration so the node's local DC differs from expectation; copy-pasted repair commands between DCs.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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