apache/cassandra · critical · ConfigurationException
Fatal configuration error; unable to start server. See…
Error message
Fatal configuration error; unable to start server. See log for stacktrace.
What it means
While instantiating the configured SeedProvider class, applySeedProvider() catches any exception from class loading or constructor invocation and rethrows a ConfigurationException whose message is '<cause message>\nFatal configuration error; unable to start server. See log for stacktrace.' — a startup-fatal wrapper indicating the seed provider could not be created.
Solutions
- Read the leading part of the message/log for the underlying cause (class not found vs constructor error)
- Set class_name to org.apache.cassandra.locator.SimpleSeedProvider (or fix the custom provider's deployment)
- Ensure any custom seed provider JAR is in lib/ on all nodes and its constructor accepts Map<String,String>
- Fix parameters (e.g. seeds string format host:port, comma-separated) in cassandra.yaml
Example fix
// cassandra.yaml before
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProviderTypo
parameters:
- seeds: "10.0.1.1"
// after
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
parameters:
- seeds: "10.0.1.1:7000" Defensive patterns
Strategy: try-catch
Validate before calling
String cls = conf.seed_provider.class_name;
try {
Class<?> c = Class.forName(cls, false, DatabaseDescriptor.class.getClassLoader());
c.getConstructor(Map.class);
} catch (Throwable t) { throw new IllegalStateException("Bad seed_provider class: " + t); } Try / catch
try { DatabaseDescriptor.applySeedProvider(); } catch (ConfigurationException e) {
String cause = e.getMessage().split("\\n")[0]; // underlying cause precedes the fatal-configuration suffix
} Prevention
- Use built-in SimpleSeedProvider unless you truly need a custom one
- Ensure custom provider JARs ship in lib/ and take a Map constructor
- Quote and format seeds strings carefully (host:port, comma-separated)
When it happens
Trigger: applySeedProvider() called with a seed_provider.class_name that cannot be loaded or constructed: misspelled FQCN, missing class (no such JAR), constructor not accepting Map, or constructor throwing (e.g. invalid parameters).
Common situations: Custom SeedProvider implementation not deployed on the node; typo in class_name; switching providers across Cassandra versions where constructor signatures changed; invalid seeds syntax causing provider-internal failure.
Related errors
- Error while getting seed node list
- seeds configuration is missing; a minimum of one seed is…
- Seeds list is now empty!
- The seed provider lists no seeds.
- A maximum number of tokens per node is supported
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/99fb5ced2c811d2a.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/config/DatabaseDescriptor.java:1675
}
public static void applySeedProvider()
{
// load the seeds for node contact points
if (conf.seed_provider == null)
{
throw new ConfigurationException("seeds configuration is missing; a minimum of one seed is required.", false);
}
try
{
Class<? extends SeedProvider> seedProviderClass =
FBUtilities.classForNameWithoutInitialization(conf.seed_provider.class_name, "seed provider", SeedProvider.class);
seedProvider = (SeedProvider) seedProviderClass.getConstructor(Map.class).newInstance(conf.seed_provider.parameters);
}
// there are about 5 checked exceptions that could be thrown here.
catch (Exception e)
{
throw new ConfigurationException(e.getMessage() + "\nFatal configuration error; unable to start server. See log for stacktrace.", true);
}
if (seedProvider.getSeeds().size() == 0)
throw new ConfigurationException("The seed provider lists no seeds.", false);
}
@VisibleForTesting
static void checkForLowestAcceptedTimeouts(Config conf)
{
if (conf.read_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("read_request_timeout", conf.read_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.read_request_timeout = new DurationSpec.LongMillisecondsBound("10ms");
}
if (conf.range_request_timeout.toMilliseconds() < LOWEST_ACCEPTED_TIMEOUT.toMilliseconds())
{
logInfo("range_request_timeout", conf.range_request_timeout, LOWEST_ACCEPTED_TIMEOUT);
conf.range_request_timeout = new DurationSpec.LongMillisecondsBound("10ms");View on GitHub (pinned to 88fd0f6a0e)