apache/seatunnel · error · IllegalArgumentException

The GCS service_account_key_file option must not be blank

Error message

The GCS service_account_key_file option must not be blank

What it means

GcsHadoopConf.configureServiceAccount translates the user option service_account_key_file into a Hadoop property for the GCS connector. If the value is blank (null/empty/whitespace) — meaning the option was declared but not given a usable value — it throws IllegalArgumentException since GCS auth cannot proceed without a key file path.

Source

Thrown at seatunnel-connectors-v2/connector-file/connector-file-gcs/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/gcs/config/GcsHadoopConf.java:100

                throw invalidBucket(bucket);
            }
        } catch (URISyntaxException e) {
            throw invalidBucket(bucket);
        }
    }

    private static IllegalArgumentException invalidBucket(String bucket) {
        return new IllegalArgumentException(
                String.format(
                        "The GCS bucket must be a bucket URI such as 'gs://my-bucket', but was '%s'. "
                                + "Configure object paths with the 'path' option.",
                        bucket));
    }

    private static void configureServiceAccount(
            Map<String, String> properties, String serviceAccountKeyFile) {
        if (StringUtils.isBlank(serviceAccountKeyFile)) {
            throw new IllegalArgumentException(
                    "The GCS service_account_key_file option must not be blank");
        }
        properties.put(GCS_SERVICE_ACCOUNT_KEY_FILE, serviceAccountKeyFile);
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set service_account_key_file to a valid, absolute path to the service account JSON key file, e.g. service_account_key_file = "/path/to/key.json"
  2. If the value comes from an env var/secret manager, verify it was actually injected at runtime (echo the resolved config)
  3. If you intended default/ADC credentials instead, remove the empty option rather than passing a blank value

Example fix

// before
GcsFile {
    service_account_key_file = ""
}
// after
GcsFile {
    service_account_key_file = "/etc/secrets/gcs-service-account.json"
}
Defensive patterns

Strategy: validation

Validate before calling

// Java: validate key file before building config
String keyFile = config.get("service_account_key_file");
if (keyFile == null || keyFile.isBlank()) {
    throw new IllegalArgumentException("service_account_key_file must be set to a non-blank JSON key path");
}
if (!java.nio.file.Files.isReadable(java.nio.file.Path.of(keyFile))) {
    throw new IllegalArgumentException("service account key not readable: " + keyFile);
}

Type guard

// Java
static boolean hasServiceAccountKey(Map<String,String> cfg) {
    String v = cfg.get("service_account_key_file");
    return v != null && !v.isBlank();
}

Try / catch

try {
    factory.createSink(...);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("service_account_key_file")) {
        logger.error("Set service_account_key_file to a valid JSON key path");
    }
    throw e;
}

Prevention

When it happens

Trigger: buildWithReadonlyConfig → configureServiceAccount called with serviceAccountKeyFile blank: the config contains service_account_key_file as an empty string or the option resolves to empty/whitespace.

Common situations: Config file has `service_account_key_file = ""` or a placeholder that an env-var substitution left empty; user forgot to set the key path while service account auth is expected; variable interpolation failure in the deployment pipeline (secret not injected).

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/df7223b7131d7e98. Report an issue: GitHub.