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

  1. 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"
  2. Remove stray leading/trailing/doubled commas from the credentials provider value
  3. If the value is templated from env/secrets, verify all interpolated parts are non-empty before job submission
  4. 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

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


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 {@link

View on GitHub (pinned to cf67b549a7)