apache/pulsar · error · IllegalArgumentException

Invalid value for BROKER_CLIENT_TRUST_CERTS_SECRET_NAME. Exp

Error message

Invalid value for BROKER_CLIENT_TRUST_CERTS_SECRET_NAME. Expected a string.

What it means

KubernetesServiceAccountTokenAuthProvider.initialize() validates the function auth config map. If BROKER_CLIENT_TRUST_CERTS_SECRET_NAME is set to a non-String, non-null value (e.g. an Integer, Boolean or Map), the provider deliberately fails fast with IllegalArgumentException because the user explicitly configured this key but with an invalid type.

Source

Thrown at pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/auth/KubernetesServiceAccountTokenAuthProvider.java:87

    private static final String DEFAULT_MOUNT_DIR = "/etc/auth";
    private static final String FUNCTION_AUTH_TOKEN = "token";
    private static final String FUNCTION_CA_CERT = "ca.crt";
    private static final String DEFAULT_CERT_PATH = DEFAULT_MOUNT_DIR + "/" + FUNCTION_CA_CERT;
    private String brokerTrustCertsSecretName;
    private long serviceAccountTokenExpirationSeconds;
    private String serviceAccountTokenAudience;

    @Override
    public void initialize(CoreV1Api coreClient, byte[] caBytes,
                           java.util.function.Function<FunctionDetails, String> namespaceCustomizerFunc,
                           Map<String, Object> config) {
        setNamespaceProviderFunc(namespaceCustomizerFunc);
        Object certSecretName = config.get(BROKER_CLIENT_TRUST_CERTS_SECRET_NAME);
        if (certSecretName instanceof String) {
            brokerTrustCertsSecretName = (String) certSecretName;
        } else if (certSecretName != null) {
            // Throw exception because user set this configuration, but it isn't valid.
            throw new IllegalArgumentException("Invalid value for " + BROKER_CLIENT_TRUST_CERTS_SECRET_NAME
                    + ". Expected a string.");
        }
        Object tokenExpirationSeconds = config.get(SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS);
        if (tokenExpirationSeconds instanceof Long) {
            serviceAccountTokenExpirationSeconds = (Long) tokenExpirationSeconds;
        } else if (tokenExpirationSeconds instanceof String) {
            try {
                serviceAccountTokenExpirationSeconds = Long.parseLong((String) tokenExpirationSeconds);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("Invalid value for " + SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS
                        + ". Expected a long.");
            }
        } else if (tokenExpirationSeconds != null) {
            // Throw exception because user set this configuration, but it isn't valid.
            throw new IllegalArgumentException("Invalid value for " + SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS
                    + ". Expected a long.");
        }
        Object tokenAudience = config.get(SERVICE_ACCOUNT_TOKEN_AUDIENCE);

View on GitHub (pinned to 820761864e)

Solutions

  1. Set BROKER_CLIENT_TRUST_CERTS_SECRET_NAME to a quoted String value containing the Kubernetes secret name.
  2. Check the config source (YAML/JSON/env parser) and quote or coerce values so numeric-looking names arrive as strings.
  3. Log/inspect the exact config value and its Java class before calling initialize to find where the wrong type enters.

Example fix

// before
config.put(BROKER_CLIENT_TRUST_CERTS_SECRET_NAME, 12345);
// after
config.put(BROKER_CLIENT_TRUST_CERTS_SECRET_NAME, String.valueOf(12345));
Defensive patterns

Strategy: validation

Validate before calling

Object v = config.get(BROKER_CLIENT_TRUST_CERTS_SECRET_NAME);
if (v != null && !(v instanceof String)) {
    throw new IllegalArgumentException("BROKER_CLIENT_TRUST_CERTS_SECRET_NAME must be a String, got " + v.getClass().getName());
}

Type guard

static boolean isStringConfig(Object v) { return v == null || v instanceof String; }

Try / catch

try {
    provider.initialize(config);
} catch (IllegalArgumentException e) {
    log.error("Function auth provider config invalid: {}", e.getMessage());
    throw new ConfigValidationException(e);
}

Prevention

When it happens

Trigger: Calling initialize(authConfig) where config.get(BROKER_CLIENT_TRUST_CERTS_SECRET_NAME) returns a non-null object that is not a String — e.g. the config was built programmatically with a number, boolean, or nested collection instead of a secret name string.

Common situations: YAML/JSON tooling parsed the secret name as a number or boolean (e.g. `12345` or `true` unquoted); a config builder passed a wrong-typed value; configuration deserialization coerced the value to an unexpected type.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/b96b1969bf0ce5e6. Report an issue: GitHub.