apache/pulsar · error · IllegalArgumentException
Kubernetes Secret should be a Map containing id/key pairs
Error message
Kubernetes Secret should be a Map containing id/key pairs
What it means
doAdmissionChecks requires every value in the function's secrets map to be a Map of id/key pairs. If any secret value is not a Map (e.g. a String, Number, or List), this IllegalArgumentException is thrown, since Kubernetes secret references cannot be expressed in another shape.
Source
Thrown at pulsar-functions/secrets/src/main/java/org/apache/pulsar/functions/secretsproviderconfigurator/KubernetesSecretsProviderConfigurator.java:138
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
- Convert each secret value to a Map with id and key fields: {"<secretId>": {"id": "<k8s-secret-name>", "key": "<key>"}}
- If you intend plain values, switch the worker's secretsProviderConfigurator to DefaultSecretsProviderConfigurator instead of the Kubernetes one
- Unquote/fix YAML so the secret entry parses as a mapping, not a scalar
Example fix
// before
secrets: {"mysecret": "db-creds"}
// after
secrets: {"mysecret": {"id": "db-creds", "key": "password"}} Defensive patterns
Strategy: type-guard
Validate before calling
void requireSecretsAreMaps(Map<String, Object> secrets) {
for (Map.Entry<String, Object> e : secrets.entrySet()) {
if (!(e.getValue() instanceof Map)) {
throw new IllegalArgumentException("Secret '" + e.getKey() + "' must be a Map of id/key pairs");
}
}
} Type guard
static boolean isSecretRefMap(Object v) {
return v instanceof Map<?, ?> m && m.containsKey("id") && m.containsKey("key");
} Try / catch
try {
admin.functions().createFunction(functionConfig);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("should be a Map")) { /* convert scalar secret values to {id, key} maps */ }
} Prevention
- Convert legacy plain-string secrets when switching to the K8s configurator
- Watch YAML quoting so entries parse as maps, not scalars
- Centralize secret config generation in one typed helper
When it happens
Trigger: Submitting a function whose secrets config contains a scalar entry, e.g. secrets: {"mysecret": "db-creds"} or a number/boolean, so the instanceof Map check fails and the else branch throws.
Common situations: using the DefaultSecretsProvider/ClearSecretsProvider syntax (plain string secret values) with KubernetesSecretsProviderConfigurator; YAML parsing a value as a scalar because of quoting; migration from another secrets provider without updating secret formats.
Related errors
- Kubernetes Secret should contain id and key
- Kubernetes Secret should contain id information
- Kubernetes Secret should contain key information
- Invalid Java object for schema type + type + : + val.getCl
- Failed to delete secrets for function %s
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a8e418026708a5ee.
Report an issue: GitHub.