{"record":{"id":"18fbbfe2068400d8","repo":"alibaba/Sentinel","slug":"null-value","errorCode":null,"errorMessage":"Null value","messagePattern":"Null value","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleUtil.java","lineNumber":224,"sourceCode":"            Object value;\n            try {\n                value = parseItemValue(item.getObject(), item.getClassType());\n            } catch (Exception ex) {\n                RecordLog.warn(\"[ParamFlowRuleUtil] Failed to parse value for item: \" + item, ex);\n                continue;\n            }\n            if (item.getCount() == null || item.getCount() < 0 || value == null) {\n                RecordLog.warn(\"[ParamFlowRuleUtil] Ignoring invalid exclusion parameter item: \" + item);\n                continue;\n            }\n            itemMap.put(value, item.getCount());\n        }\n        return itemMap;\n    }\n\n    static Object parseItemValue(String value, String classType) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"Null value\");\n        }\n        if (StringUtil.isBlank(classType)) {\n            // If the class type is not provided, then treat it as string.\n            return value;\n        }\n        // Handle primitive type.\n        if (int.class.toString().equals(classType) || Integer.class.getName().equals(classType)) {\n            return Integer.parseInt(value);\n        } else if (boolean.class.toString().equals(classType) || Boolean.class.getName().equals(classType)) {\n            return Boolean.parseBoolean(value);\n        } else if (long.class.toString().equals(classType) || Long.class.getName().equals(classType)) {\n            return Long.parseLong(value);\n        } else if (double.class.toString().equals(classType) || Double.class.getName().equals(classType)) {\n            return Double.parseDouble(value);\n        } else if (float.class.toString().equals(classType) || Float.class.getName().equals(classType)) {\n            return Float.parseFloat(value);\n        } else if (byte.class.toString().equals(classType) || Byte.class.getName().equals(classType)) {\n            return Byte.parseByte(value);","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-extension/sentinel-parameter-flow-control/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/param/ParamFlowRuleUtil.java#L206-L242","documentation":"Thrown by ParamFlowRuleUtil.parseItemValue(String, String) when the value string of a hot-parameter flow rule's exclusion item is null. Sentinel parses string-encoded param flow rules (e.g. loaded from properties file, Nacos, Apollo, or ZooKeeper datasources) into typed objects; a rule entry whose value field is absent yields null, and this method refuses it with IllegalArgumentException(\"Null value\"). It never happens for rules built programmatically with non-null values.","triggerScenarios":"Loading a ParamFlowRule from a dynamic configuration source where paramFlowItemList contains an item with a missing/absent \"value\" JSON field (e.g. {\"classType\":\"int\",\"count\":2} with no \"value\"), causing fillExceptionFlowProperties/parseItemValue to receive null.","commonSituations":"Typo or omission of the \"value\" key in a JSON/YAML param flow rule pushed to Nacos/Apollo; a datasource schema change that drops the value field; manually hand-edited rule files. Note the callers guard item.getCount() and value in parseExclusionItems, but other parseItemValue call sites (fillExceptionFlowProperties for map/object values) pass config data straight through.","solutions":["Inspect the failing ParamFlowRule configuration and add the missing \"value\" field to every entry in paramFlowItemList","Validate rules before publishing: every paramFlowItem / paramFlowItemList entry must have a non-null value and non-negative count","If rules are machine-generated, fix the producer so it never serializes an item without a value","Wrap rule loading in a try-catch for IllegalArgumentException so one bad rule does not crash startup; Sentinel already logs and skips invalid items in some paths (RecordLog.warn \"Ignoring invalid exclusion parameter item\")"],"exampleFix":"// before (rule JSON pushed to Nacos)\n{\"resource\":\"foo\",\"paramIdx\":0,\"paramFlowItemList\":[{\"classType\":\"int\",\"count\":2}]}\n\n// after\n{\"resource\":\"foo\",\"paramIdx\":0,\"paramFlowItemList\":[{\"classType\":\"int\",\"count\":2,\"value\":\"123\"}]}","handlingStrategy":"validation","validationCode":"// before publishing a ParamFlowRule, verify every exclusion item has a value\nfor (ParamFlowItem item : rule.getParamFlowItemList()) {\n    if (item == null || item.getObject() == null && parseableValueMissing(item)) {\n        throw new IllegalStateException(\"paramFlowItem without value for rule \" + rule.getResource());\n    }\n}\n// simpler: validate the raw config map/JSON before conversion\njsonItems.forEach(i -> Objects.requireNonNull(i.get(\"value\"), \"paramFlowItem.value required\"));","typeGuard":null,"tryCatchPattern":"try {\n    ParamFlowRuleManager.loadRules(rules);\n} catch (IllegalArgumentException e) {\n    log.warn(\"Rejected invalid param flow rule config: {}\", e.getMessage());\n    // keep last-good rules instead of crashing startup\n}","preventionTips":["Schema-validate datasource rule payloads (require value + count on each paramFlowItem) in CI","Treat rule-loading as untrusted input: one bad rule should be logged and skipped, not fatal"],"tags":["sentinel","flow-control","rule-config","validation"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}