apache/seatunnel · error · IllegalArgumentException

transport.aes-secret-key-base64 is required when transport.e

Error message

transport.aes-secret-key-base64 is required when transport.encryption is "aes_gcm".

What it means

EdgeTransportConfig validates the transport configuration at startup. When transport.encryption is set to "aes_gcm", packets are encrypted with AES-GCM, which requires a shared secret; the code reads transport.aes-secret-key-base64 and throws IllegalArgumentException if it is absent or blank. This fail-fast check prevents starting a transport that could not encrypt traffic.

Source

Thrown at seatunnel-edge-agent/seatunnel-edge-agent-transport/src/main/java/org/apache/seatunnel/edge/agent/transport/config/EdgeTransportConfig.java:71

        this.endpoint = trimmedEndpoint;

        String authType = config.get(EdgeTransportOptions.AUTH_TYPE);
        validateAuthType(authType);
        String rawToken = config.getOptional(EdgeTransportOptions.TOKEN).orElse(null);
        if (rawToken == null || rawToken.trim().isEmpty()) {
            throw new IllegalArgumentException("transport.token is required.");
        }
        this.token = rawToken.trim();

        EdgePacketMode.from(config.get(EdgeTransportOptions.PACKET_MODE));
        EdgePacketCompressionType.from(config.get(EdgeTransportOptions.COMPRESSION));
        EdgePacketEncryptionType encryption =
                EdgePacketEncryptionType.from(config.get(EdgeTransportOptions.ENCRYPTION));
        if (encryption == EdgePacketEncryptionType.AES_GCM) {
            String key =
                    config.getOptional(EdgeTransportOptions.AES_SECRET_KEY_BASE64).orElse(null);
            if (key == null || key.trim().isEmpty()) {
                throw new IllegalArgumentException(
                        "transport.aes-secret-key-base64 is required when transport.encryption"
                                + " is \"aes_gcm\".");
            }
        }

        this.connectTimeoutMs = config.get(EdgeTransportOptions.CONNECT_TIMEOUT_MS);
        this.readTimeoutMs = config.get(EdgeTransportOptions.READ_TIMEOUT_MS);
        this.maxBatchSendAttempts = config.get(EdgeTransportOptions.MAX_BATCH_SEND_ATTEMPTS);
        this.initialBackoffMs = config.get(EdgeTransportOptions.INITIAL_BACKOFF_MS);
        this.maxBackoffMs = config.get(EdgeTransportOptions.MAX_BACKOFF_MS);
        this.maxReconnectCycles = config.get(EdgeTransportOptions.MAX_RECONNECT_CYCLES);
    }

    public static EdgeTransportConfig from(ReadonlyConfig config) {
        return new EdgeTransportConfig(config);
    }

    public static long computeBackoffMillis(long attempt, long initial, long max) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set transport.aes-secret-key-base64 in the agent config to a Base64-encoded 128/192/256-bit key (e.g. generate with `openssl rand -base64 32`).
  2. If encryption is not needed, change transport.encryption to "none" (or remove it) so the key is not required.
  3. If the key is injected via environment placeholder, verify the variable is actually set in the agent's runtime environment.
  4. Confirm there are no typos in the option name transport.aes-secret-key-base64 and that the key is in the config file actually loaded.

Example fix

// before
transport {
  encryption = "aes_gcm"
}

// after
transport {
  encryption = "aes_gcm"
  aes-secret-key-base64 = "bXktMzItYnl0ZS1zZWNyZXQta2V5LTEyMzQ1Njc4"
}
Defensive patterns

Strategy: validation

Validate before calling

Config cfg = ConfigProvider.getConfig();
String encryption = cfg.hasPath("transport.encryption") ? cfg.getString("transport.encryption") : "none";
if ("aes_gcm".equalsIgnoreCase(encryption)
        && (!cfg.hasPath("transport.aes-secret-key-base64")
            || cfg.getString("transport.aes-secret-key-base64").trim().isEmpty())) {
    throw new IllegalStateException("transport.aes-secret-key-base64 must be set when transport.encryption=aes_gcm");
}

Type guard

boolean hasAesKey(Config cfg) {
    return !"aes_gcm".equalsIgnoreCase(cfg.getString("transport.encryption"))
        || cfg.hasPath("transport.aes-secret-key-base64")
            && !cfg.getString("transport.aes-secret-key-base64").trim().isEmpty();
}

Try / catch

try {
    EdgeTransportConfig transportConfig = new EdgeTransportConfig(config);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("aes-secret-key-base64")) {
        LOG.error("Transport encryption requires a Base64 AES key; fix config and restart", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructing EdgeTransportConfig (from a Config) with EdgeTransportOptions.ENCRYPTION resolved to AES_GCM while config.getOptional(EdgeTransportOptions.AES_SECRET_KEY_BASE64) returns empty or a whitespace-only string.

Common situations: User sets transport.encryption = "aes_gcm" in the agent HOCON file but forgets the key entry; the key is supplied via an env var that is not exported; a copy-pasted key consisting of only spaces; upgrading from "none" encryption to "aes_gcm" without adding the new option.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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