apache/pulsar · error · IllegalArgumentException

Invalid value for SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS.

Error message

Invalid value for SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS. Expected a long.

What it means

initialize() accepts SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS as a Long or a numeric String, but throws IllegalArgumentException when the String cannot be parsed by Long.parseLong. This fail-fast validation prevents silently running with an unset token expiration.

Source

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

                           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);
        if (tokenAudience instanceof String) {
            serviceAccountTokenAudience = (String) tokenAudience;
        } else if (tokenAudience != null) {
            throw new IllegalArgumentException("Invalid value for " + SERVICE_ACCOUNT_TOKEN_AUDIENCE
                    + ". Expected a string.");
        }
    }

    @Override
    public void configureAuthenticationConfig(AuthenticationConfig authConfig,

View on GitHub (pinned to 820761864e)

Solutions

  1. Change the value to a plain integer string (e.g. "7200") or an unquoted integer in the config.
  2. If a duration suffix is needed, parse/convert it to seconds yourself before passing it into the auth config.
  3. Trim whitespace and verify the value matches ^[0-9]+$ before calling initialize.

Example fix

// before
config.put(SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS, "1h");
// after
config.put(SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS, 3600L);
Defensive patterns

Strategy: validation

Validate before calling

Object v = config.get(SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS);
if (v instanceof String && !v.toString().trim().matches("^\\d+$")) {
    throw new IllegalArgumentException("SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS must be a plain integer (seconds), got: " + v);
}

Type guard

static boolean isValidExpiration(Object v) {
    return v == null || v instanceof Long || (v instanceof String && ((String) v).trim().matches("^\\d+$"));
}

Try / catch

try {
    provider.initialize(config);
} catch (IllegalArgumentException e) {
    log.error("Token expiration config invalid (use plain seconds, no unit suffix): {}", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: SERVICE_ACCOUNT_TOKEN_EXPIRATION_SECONDS is provided as a String containing non-numeric text (e.g. "1h", "7200s", "abc") so Long.parseLong throws NumberFormatException and the error is rethrown.

Common situations: Users write durations with unit suffixes ("30m") or formatted numbers ("7,200") in YAML; config is read from an env var containing whitespace or a unit suffix.

Related errors


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