alibaba/nacos · error · IllegalArgumentException
Plugin config value cannot be null: + key
Error message
Plugin config value cannot be null: + key
What it means
Thrown by the private value() helper in NacosAuthPluginConfig when the effective config map explicitly contains a key but its mapped value is null. This is distinct from a missing key (which returns the default) — a present-but-null entry is treated as a programming/serialization defect. It surfaces as an IllegalArgumentException during from().
Source
Thrown at plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/configuration/NacosAuthPluginConfig.java:116
long tokenExpireSeconds = parsePositiveLong(value(config, TOKEN_EXPIRE_SECONDS,
AuthConstants.DEFAULT_TOKEN_EXPIRE_SECONDS.toString()), TOKEN_EXPIRE_SECONDS);
boolean tokenCacheEnabled = parseBoolean(value(config, TOKEN_CACHE_ENABLE,
Boolean.toString(DEFAULT_TOKEN_CACHE_ENABLE)), TOKEN_CACHE_ENABLE);
boolean cachingEnabled = parseBoolean(value(config, CACHING_ENABLED,
Boolean.toString(DEFAULT_CACHING_ENABLED)), CACHING_ENABLED);
boolean anonymousAiEnabled = parseBoolean(value(config, ANONYMOUS_AI_ENABLED,
Boolean.toString(DEFAULT_ANONYMOUS_AI_ENABLED)), ANONYMOUS_AI_ENABLED);
return new NacosAuthPluginConfig(tokenSecretKey, tokenExpireSeconds, tokenCacheEnabled,
cachingEnabled, anonymousAiEnabled);
}
private static String value(Map<String, String> config, String key, String defaultValue) {
if (config == null || !config.containsKey(key)) {
return defaultValue;
}
String result = config.get(key);
if (result == null) {
throw new IllegalArgumentException("Plugin config value cannot be null: " + key);
}
return result;
}
private static long parsePositiveLong(String value, String key) {
try {
long result = Long.parseLong(value);
if (result <= 0) {
throw new IllegalArgumentException("Plugin config value must be positive: " + key);
}
return result;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Plugin config value is not a number: " + key, e);
}
}
private static boolean parseBoolean(String value, String key) {
if (!Boolean.TRUE.toString().equalsIgnoreCase(value)View on GitHub (pinned to 9b989acdf1)
Solutions
- Audit the config map for any entry whose value is null before calling NacosAuthPluginConfig.from().
- If a key should be unset, remove it from the map entirely so value() falls back to the default.
- Sanitize the map upstream: strip null-valued entries (e.g., map.values().removeIf(Objects::isNull)).
Example fix
// before
Map<String,String> cfg = new HashMap<>();
cfg.put("token.expire.seconds", null); // present-but-null -> error 1261
NacosAuthPluginConfig.from(cfg, true);
// after
Map<String,String> cfg = new HashMap<>();
cfg.remove("token.expire.seconds"); // absent -> uses default
NacosAuthPluginConfig.from(cfg, true); Defensive patterns
Strategy: validation
Validate before calling
// Strip null-valued entries before parsing.
Map<String, String> safe = new LinkedHashMap<>();
if (config != null) {
config.forEach((k, v) -> { if (v != null) safe.put(k, v); });
}
NacosAuthPluginConfig.from(safe, tokenSecretRequired); Prevention
- Never insert null values into the plugin config map — omit the key instead.
- When loading from Properties, filter out keys whose value is null before building the map.
- Unit-test the config-building path with assertions that no value is null.
When it happens
Trigger: A config map is built programmatically (e.g., in a plugin-config adapter, test fixture, or a deserialized properties source) with config.put("token.expire.seconds", null) — the key is present but the value is null, so config.get(key) returns null and the throw fires.
Common situations: Loading plugin config from a properties file where a key is declared with no value (Properties can yield null on get for an empty assignment in some loaders); test helpers that put null placeholders; a config-reload path that copies a sparse map.
Related errors
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/64811a61aec4498c.
Report an issue: GitHub.