apache/pulsar · error · IllegalArgumentException

Kubernetes Secret should contain key information

Error message

Kubernetes Secret should contain key information

What it means

In doAdmissionChecks, each Kubernetes secret entry must contain the key field ('key') naming which key inside the Kubernetes Secret to expose. If the entry is a Map containing 'id' but missing keyKey, this IllegalArgumentException is thrown.

Source

Thrown at pulsar-functions/secrets/src/main/java/org/apache/pulsar/functions/secretsproviderconfigurator/KubernetesSecretsProviderConfigurator.java:135

    public void doAdmissionChecks(AppsV1Api appsV1Api, CoreV1Api coreV1Api, String jobNamespace, String jobName,
                                  FunctionDetails functionDetails) {
        if (!StringUtils.isEmpty(functionDetails.getSecretsMap())) {
            Type type = new TypeToken<Map<String, Object>>() {
            }.getType();
            Map<String, Object> secretsMap = new Gson().fromJson(functionDetails.getSecretsMap(), type);

            for (Object object : secretsMap.values()) {
                if (object instanceof Map) {
                    @SuppressWarnings("unchecked") // secret values are expected to be Map<String, String>
                    Map<String, String> kubernetesSecret = (Map<String, String>) object;
                    if (kubernetesSecret.size() < 2) {
                        throw new IllegalArgumentException("Kubernetes Secret should contain id and key");
                    }
                    if (!kubernetesSecret.containsKey(idKey)) {
                        throw new IllegalArgumentException("Kubernetes Secret should contain id information");
                    }
                    if (!kubernetesSecret.containsKey(keyKey)) {
                        throw new IllegalArgumentException("Kubernetes Secret should contain key information");
                    }
                } else {
                    throw new IllegalArgumentException("Kubernetes Secret should be a Map containing id/key pairs");
                }
            }
        }
    }
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Add the 'key' field naming the entry inside the Kubernetes Secret: {"id": "<secret-name>", "key": "<key-inside-secret>"}
  2. Create the needed key in the Kubernetes Secret and reference it in your secrets config
  3. Validate each secret entry has both id and key before submitting the function

Example fix

// before
secrets: {"mysecret": {"id": "db-creds"}}
// after
secrets: {"mysecret": {"id": "db-creds", "key": "password"}}
Defensive patterns

Strategy: validation

Validate before calling

void requireSecretKey(Map<String, Object> secrets) {
    for (Map.Entry<String, Object> e : secrets.entrySet()) {
        Map<?, ?> m = (Map<?, ?>) e.getValue();
        if (!m.containsKey("key")) {
            throw new IllegalArgumentException("Secret '" + e.getKey() + "' missing 'key'");
        }
    }
}

Type guard

static boolean hasSecretKey(Object v) {
    return v instanceof Map<?, ?> m && m.containsKey("key");
}

Try / catch

try {
    admin.functions().createFunction(functionConfig);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("key information")) { /* add 'key' field naming the k8s secret entry */ }
}

Prevention

When it happens

Trigger: doAdmissionChecks receives a secrets entry like {"id": "db-creds"} or {"id": "db-creds", "optional": "true"} — a Map that identifies the Kubernetes Secret but not the key inside it.

Common situations: users think specifying the secret name is enough and expect all keys to be mounted; truncation of config when only one field was serialized; mixing the ClearSecretsProvider plain-string format with the K8s format.

Related errors


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