apache/cassandra · critical · ConfigurationException
num_tokens must be >= 1
Error message
num_tokens must be >= 1
What it means
BootStrapper.getBootstrapTokens reads num_tokens from DatabaseDescriptor; if configured below 1 the bootstrap cannot allocate any tokens and throws ConfigurationException. This validates cassandra.yaml's num_tokens before token allocation begins.
Source
Thrown at src/java/org/apache/cassandra/dht/BootStrapper.java:239
public static Collection<Token> getBootstrapTokens(final ClusterMetadata metadata, InetAddressAndPort address) throws ConfigurationException
{
String allocationKeyspace = DatabaseDescriptor.getAllocateTokensForKeyspace();
Integer allocationLocalRf = DatabaseDescriptor.getAllocateTokensForLocalRf();
Collection<String> initialTokens = DatabaseDescriptor.getInitialTokens();
if (initialTokens.size() > 0 && allocationKeyspace != null)
logger.warn("manually specified tokens override automatic allocation");
// if user specified tokens, use those
if (initialTokens.size() > 0)
{
Collection<Token> tokens = getSpecifiedTokens(metadata, initialTokens);
BootstrapDiagnostics.useSpecifiedTokens(address, allocationKeyspace, tokens, DatabaseDescriptor.getNumTokens());
return tokens;
}
int numTokens = DatabaseDescriptor.getNumTokens();
if (numTokens < 1)
throw new ConfigurationException("num_tokens must be >= 1");
if (allocationKeyspace != null)
return allocateTokens(metadata, address, allocationKeyspace, numTokens);
if (allocationLocalRf != null)
return allocateTokens(metadata, address, allocationLocalRf, numTokens);
if (numTokens == 1)
logger.warn("Picking random token for a single vnode. You should probably add more vnodes and/or use the automatic token allocation mechanism.");
Collection<Token> tokens = getRandomTokens(metadata, numTokens);
BootstrapDiagnostics.useRandomTokens(address, metadata, numTokens, tokens);
return tokens;
}
private static Collection<Token> getSpecifiedTokens(final ClusterMetadata metadata,
Collection<String> initialTokens)
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Set num_tokens to a positive integer (default 16 in modern versions, 1 for single-token-per-node deployments) in cassandra.yaml and restart bootstrap.
- Check for environment/config templating that substituted 0 (e.g. ${NUM_TOKENS} defaulting empty->0).
- If using the legacy initial_token path, num_tokens must still be >= 1; ensure it is not disabled via a broken override.
- Validate the config before startup with a config-check or by inspecting effective values in the logs.
Example fix
// cassandra.yaml before num_tokens: 0 // after num_tokens: 16
Defensive patterns
Strategy: validation
Validate before calling
// Before startup/bootstrap
int numTokens = Integer.parseInt(config.getOrDefault("num_tokens", "16"));
if (numTokens < 1)
throw new IllegalArgumentException("num_tokens must be >= 1, got " + numTokens); Try / catch
try { node.bootstrap(); }
catch (ConfigurationException e) {
if (e.getMessage().contains("num_tokens must be >= 1"))
// fix cassandra.yaml and restart
}
Prevention
- Validate cassandra.yaml values before rollout
- Check templating/CI pipelines for variables defaulting to 0
- Keep num_tokens at the version default unless intentional
- Log effective config at startup and alert on suspicious values
When it happens
Trigger: Starting a node to bootstrap with num_tokens set to 0 or a negative value in cassandra.yaml (or via system property override).
Common situations: Hand-edited cassandra.yaml with num_tokens: 0; scripted config generation that computed 0 tokens; copying config templates with placeholders left unexpanded; confusion between num_tokens and allocate_tokens_for_local_replication_factor.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- A maximum number of %d tokens per node is supported
- initial_token was set but num_tokens is not!
- Bootstrapping to existing token " + tokenString + " is not a
- manually specified tokens override automatic allocation
- Picking random token for a single vnode. You should probabl
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/86bf74ab7c71382b.
Report an issue: GitHub.