{"record":{"id":"18921dd3acf7f322","repo":"apache/seatunnel","slug":"the-s3a-credentials-provider-chain-configured-via","errorCode":null,"errorMessage":"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.","messagePattern":"The S3A credentials provider chain configured via '(.+?)' contains an empty class name \\('(.+?)'\\)\\. Please ensure every entry between separators is a fully-qualified provider class name\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-s3/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/s3/config/S3HadoopConf.java","lineNumber":146,"sourceCode":"     * separators while still allowing an interior empty entry such as {@code \"A,,B\"} to fail with\n     * an actionable error.\n     *\n     * <p>The provider is ultimately instantiated on every worker by Hadoop S3A, and the classpath\n     * of the node building this configuration (client/coordinator, or a module embedding this\n     * connector) may legitimately differ from the workers' — the provider jar only has to be\n     * present where S3A actually runs (for example under {@code ${SEATUNNEL_HOME}/lib} on every\n     * cluster node). A class that cannot be resolved here is therefore only logged as a warning,\n     * never rejected. Only a class that resolves but does not implement the AWS credentials\n     * provider contract, or a malformed (empty) chain entry, fails fast because that configuration\n     * cannot work on any node.\n     *\n     * @param credentialsProvider the raw option value (single class or comma-separated chain)\n     */\n    private static void checkCredentialsProviders(String credentialsProvider) {\n        String[] providerClassNames = StringUtils.getTrimmedStrings(credentialsProvider);\n        for (String providerClassName : providerClassNames) {\n            if (providerClassName.isEmpty()) {\n                throw new IllegalArgumentException(\n                        String.format(\n                                \"The S3A credentials provider chain configured via '%s' contains an \"\n                                        + \"empty class name ('%s'). Please ensure every entry between \"\n                                        + \"separators is a fully-qualified provider class name.\",\n                                S3FileBaseOptions.S3A_AWS_CREDENTIALS_PROVIDER_CLASS.key(),\n                                credentialsProvider));\n            }\n            checkCredentialsProviderClass(providerClassName);\n        }\n    }\n\n    /**\n     * Validates a single S3A credentials provider class as far as the local classpath allows.\n     *\n     * <p>The lookup tries the thread context classloader first, then falls back to the classloader\n     * that loaded this connector. Under the Zeta plugin classloader the context classloader may be\n     * {@code null} or unrelated to the connector, so the fallback ensures a provider bundled with\n     * the connector (including the default {@link","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-file/connector-file-s3/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/s3/config/S3HadoopConf.java#L128-L164","documentation":"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.","triggerScenarios":"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.","commonSituations":",-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.","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"],"exampleFix":"// before\ns3a_aws_credentials_provider_class = \"org.apache.hadoop.fs.s3a.auth.EnvironmentVariableCredentialsProvider,\"\n// after\ns3a_aws_credentials_provider_class = \"org.apache.hadoop.fs.s3a.auth.EnvironmentVariableCredentialsProvider\"","handlingStrategy":"validation","validationCode":"// Java: validate provider chain before building config\nString chain = config.get(\"s3a_aws_credentials_provider_class\");\nif (chain != null) {\n    for (String name : chain.split(\",\")) {\n        if (name.trim().isEmpty()) {\n            throw new IllegalArgumentException(\"Empty entry in credentials provider chain: \" + chain);\n        }\n    }\n}","typeGuard":"// Java\nstatic boolean isValidProviderChain(String chain) {\n    if (chain == null) return true;\n    return java.util.Arrays.stream(chain.split(\",\"))\n        .allMatch(s -> !s.trim().isEmpty());\n}","tryCatchPattern":"try {\n    S3HadoopConf.buildWithReadOnlyConfig(readonlyConfig);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"empty class name\")) {\n        logger.error(\"Fix credentials provider chain: no empty segments allowed\");\n    }\n    throw e;\n}","preventionTips":["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"],"tags":["s3","config","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}