{"record":{"id":"64811a61aec4498c","repo":"alibaba/nacos","slug":"plugin-config-value-cannot-be-null-key","errorCode":null,"errorMessage":"Plugin config value cannot be null:  + key","messagePattern":"Plugin config value cannot be null:  \\+ key","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/configuration/NacosAuthPluginConfig.java","lineNumber":116,"sourceCode":"        long tokenExpireSeconds = parsePositiveLong(value(config, TOKEN_EXPIRE_SECONDS,\n            AuthConstants.DEFAULT_TOKEN_EXPIRE_SECONDS.toString()), TOKEN_EXPIRE_SECONDS);\n        boolean tokenCacheEnabled = parseBoolean(value(config, TOKEN_CACHE_ENABLE,\n            Boolean.toString(DEFAULT_TOKEN_CACHE_ENABLE)), TOKEN_CACHE_ENABLE);\n        boolean cachingEnabled = parseBoolean(value(config, CACHING_ENABLED,\n            Boolean.toString(DEFAULT_CACHING_ENABLED)), CACHING_ENABLED);\n        boolean anonymousAiEnabled = parseBoolean(value(config, ANONYMOUS_AI_ENABLED,\n            Boolean.toString(DEFAULT_ANONYMOUS_AI_ENABLED)), ANONYMOUS_AI_ENABLED);\n        return new NacosAuthPluginConfig(tokenSecretKey, tokenExpireSeconds, tokenCacheEnabled,\n            cachingEnabled, anonymousAiEnabled);\n    }\n    \n    private static String value(Map<String, String> config, String key, String defaultValue) {\n        if (config == null || !config.containsKey(key)) {\n            return defaultValue;\n        }\n        String result = config.get(key);\n        if (result == null) {\n            throw new IllegalArgumentException(\"Plugin config value cannot be null: \" + key);\n        }\n        return result;\n    }\n    \n    private static long parsePositiveLong(String value, String key) {\n        try {\n            long result = Long.parseLong(value);\n            if (result <= 0) {\n                throw new IllegalArgumentException(\"Plugin config value must be positive: \" + key);\n            }\n            return result;\n        } catch (NumberFormatException e) {\n            throw new IllegalArgumentException(\"Plugin config value is not a number: \" + key, e);\n        }\n    }\n    \n    private static boolean parseBoolean(String value, String key) {\n        if (!Boolean.TRUE.toString().equalsIgnoreCase(value)","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/plugin-default-impl/nacos-default-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/configuration/NacosAuthPluginConfig.java#L98-L134","documentation":"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().","triggerScenarios":"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.","commonSituations":"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.","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))."],"exampleFix":"// before\nMap<String,String> cfg = new HashMap<>();\ncfg.put(\"token.expire.seconds\", null); // present-but-null -> error 1261\nNacosAuthPluginConfig.from(cfg, true);\n\n// after\nMap<String,String> cfg = new HashMap<>();\ncfg.remove(\"token.expire.seconds\"); // absent -> uses default\nNacosAuthPluginConfig.from(cfg, true);","handlingStrategy":"validation","validationCode":"// Strip null-valued entries before parsing.\nMap<String, String> safe = new LinkedHashMap<>();\nif (config != null) {\n    config.forEach((k, v) -> { if (v != null) safe.put(k, v); });\n}\nNacosAuthPluginConfig.from(safe, tokenSecretRequired);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["config","validation","null-handling"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}