apache/seatunnel · error · IllegalArgumentException
The S3A credentials provider chain configured via
Error message
The S3A credentials provider chain configured via '%s' contains an empty class name ('%s'). Please ensure every entry between separators is a fully-qualified provider class name. What it means
S3HadoopConf.checkCredentialsProviders validates the fs.s3a.aws.credentials.provider chain before mapping it into Hadoop properties. After splitting on separators with StringUtils.getTrimmedStrings, any resulting entry that is empty (e.g. from a doubled comma or a leading/trailing comma) is rejected with IllegalArgumentException, because an empty class name would fail at Hadoop reflection time with a confusing error.
Solutions
- Fix the provider chain so every comma-separated entry is a fully-qualified class name with no empty segments, e.g. "org.apache.hadoop.fs.s3a.auth.EnvironmentVariableCredentialsProvider"
- Remove stray leading/trailing/doubled commas from the credentials provider value
- If the value is templated from env/secrets, verify all interpolated parts are non-empty before job submission
- Explicitly specify a valid default such as com.amazonaws.auth.EnvironmentVariableCredentialsProvider or SimpleAWSCredentialsProvider instead of an empty entry
Example fix
// before s3a_aws_credentials_provider_class = "org.apache.hadoop.fs.s3a.auth.EnvironmentVariableCredentialsProvider," // after s3a_aws_credentials_provider_class = "org.apache.hadoop.fs.s3a.auth.EnvironmentVariableCredentialsProvider"
Defensive patterns
Strategy: validation
Validate before calling
// Java: validate provider chain before building config
String chain = config.get("s3a_aws_credentials_provider_class");
if (chain != null) {
for (String name : chain.split(",")) {
if (name.trim().isEmpty()) {
throw new IllegalArgumentException("Empty entry in credentials provider chain: " + chain);
}
}
} Type guard
// Java
static boolean isValidProviderChain(String chain) {
if (chain == null) return true;
return java.util.Arrays.stream(chain.split(","))
.allMatch(s -> !s.trim().isEmpty());
} Try / catch
try {
S3HadoopConf.buildWithReadOnlyConfig(readonlyConfig);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("empty class name")) {
logger.error("Fix credentials provider chain: no empty segments allowed");
}
throw e;
} Prevention
- Avoid building comma-separated provider lists by string concatenation of possibly-empty values
- Trim and filter empty segments before assignment
- Verify templated/env values resolve before submission
- Prefer configuring one explicit provider class over long chains
When it happens
Trigger: buildWithReadOnlyConfig → checkCredentialsProviders receives an s3a-aws-credentials-provider-class value containing empty segments, e.g. "com.a.A,,com.b.B" or ",com.a.A" or a value that is only commas/whitespace.
Common situations: ,-separated provider list assembled by concatenating variables where one part was empty; trailing comma left from copy-paste; env var/secret placeholder resolved to nothing inside the chain; typo leaving two commas adjacent.
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
- At least one sink plugin must be configured.
- At least one source plugin must be configured.
- AzureCosmosDB requires uri, endpoint, or connection string…
- Cannot specify both ' ' and root-level ' '.
- checkResult.getMsg()
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/18921dd3acf7f322.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-file/connector-file-s3/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/s3/config/S3HadoopConf.java:146
* separators while still allowing an interior empty entry such as {@code "A,,B"} to fail with
* an actionable error.
*
* <p>The provider is ultimately instantiated on every worker by Hadoop S3A, and the classpath
* of the node building this configuration (client/coordinator, or a module embedding this
* connector) may legitimately differ from the workers' — the provider jar only has to be
* present where S3A actually runs (for example under {@code ${SEATUNNEL_HOME}/lib} on every
* cluster node). A class that cannot be resolved here is therefore only logged as a warning,
* never rejected. Only a class that resolves but does not implement the AWS credentials
* provider contract, or a malformed (empty) chain entry, fails fast because that configuration
* cannot work on any node.
*
* @param credentialsProvider the raw option value (single class or comma-separated chain)
*/
private static void checkCredentialsProviders(String credentialsProvider) {
String[] providerClassNames = StringUtils.getTrimmedStrings(credentialsProvider);
for (String providerClassName : providerClassNames) {
if (providerClassName.isEmpty()) {
throw new IllegalArgumentException(
String.format(
"The S3A credentials provider chain configured via '%s' contains an "
+ "empty class name ('%s'). Please ensure every entry between "
+ "separators is a fully-qualified provider class name.",
S3FileBaseOptions.S3A_AWS_CREDENTIALS_PROVIDER_CLASS.key(),
credentialsProvider));
}
checkCredentialsProviderClass(providerClassName);
}
}
/**
* Validates a single S3A credentials provider class as far as the local classpath allows.
*
* <p>The lookup tries the thread context classloader first, then falls back to the classloader
* that loaded this connector. Under the Zeta plugin classloader the context classloader may be
* {@code null} or unrelated to the connector, so the fallback ensures a provider bundled with
* the connector (including the default {@linkView on GitHub (pinned to cf67b549a7)