{"record":{"id":"6a05cf8726f621df","repo":"alibaba/spring-cloud-alibaba","slug":"sentinel-rule-convert-error","errorCode":null,"errorMessage":"sentinel rule convert error: {}","messagePattern":"sentinel rule convert error: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/SentinelConverter.java","lineNumber":95,"sourceCode":"\n\t\tif (StringUtils.isEmpty(source)) {\n\t\t\tlog.info(\"converter can not convert rules because source is empty\");\n\t\t\treturn ruleCollection;\n\t\t}\n\t\ttry {\n\t\t\tList sourceArray = objectMapper.readValue(source,\n\t\t\t\t\tnew TypeReference<List<HashMap>>() {\n\t\t\t\t\t});\n\n\t\t\tfor (Object obj : sourceArray) {\n\t\t\t\ttry {\n\t\t\t\t\tString item = objectMapper.writeValueAsString(obj);\n\t\t\t\t\tOptional.ofNullable(convertRule(item))\n\t\t\t\t\t\t\t.ifPresent(convertRule -> ruleCollection.add(convertRule));\n\t\t\t\t}\n\t\t\t\tcatch (JacksonException e) {\n\t\t\t\t\tlog.error(\"sentinel rule convert error: \" + e.getMessage(), e);\n\t\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\t\"sentinel rule convert error: \" + e.getMessage(), e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tif (e instanceof RuntimeException runtimeException) {\n\t\t\t\tthrow runtimeException;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new RuntimeException(\"convert error: \" + e.getMessage(), e);\n\t\t\t}\n\t\t}\n\t\treturn ruleCollection;\n\t}\n\n\tprivate Object convertRule(String ruleStr) {\n\t\treturn objectMapper.readValue(ruleStr, ruleClass);\n\t}","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/alibaba/spring-cloud-alibaba/blob/115d5901102009492e05d5ec18c3f79cad4077d0/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-datasource/src/main/java/com/alibaba/cloud/sentinel/datasource/converter/SentinelConverter.java#L77-L113","documentation":"Thrown by SentinelConverter.convert during Sentinel rule deserialization when an individual rule item fails to convert from JSON to the target rule class (FlowRule, DegradeRule, etc.). The outer loop parses a JSON array into List<HashMap>, then each element is serialized back to a JSON string and passed to convertRule which calls objectMapper.readValue(ruleStr, ruleClass). If the individual rule JSON does not match the schema of the target rule class, a JacksonException is caught and re-thrown as IllegalArgumentException with the Jackson error message appended.","triggerScenarios":"A Sentinel datasource (file, Nacos, Apollo, etc.) provides rule data as a JSON array where one or more elements have fields that cannot be deserialized into the configured rule class. For example, a FlowRule JSON with a string value where an integer is expected, an unknown enum value, or a missing required field that the Jackson ObjectMapper rejects in strict mode.","commonSituations":"1) Sentinel rule JSON format changed between versions and old rules have deprecated/removed fields. 2) Rule data authored manually with type mismatches (e.g., threshold as string '100' instead of number 100 in strict mode). 3) Wrong data-type configuration: datasource configured as flow-rules but the JSON contains degrade-rule structure. 4) Jackson strict mode rejects extra/unknown fields in the rule JSON.","solutions":["Inspect the Sentinel rule JSON in your datasource (file, Nacos config, etc.) and validate each element against the expected rule class schema (FlowRule, DegradeRule, SystemRule, AuthorityRule, or ParamFlowRule).","Fix the specific rule element that has the type mismatch or invalid field value — the Jackson error message in the exception identifies the field.","Ensure the datasource data-type matches the rule content (e.g., spring.cloud.sentinel.datasource.<name>.<type>.data-type=flow for FlowRule JSON).","If upgrading Sentinel versions, check the migration guide for rule schema changes."],"exampleFix":"// before (broken — threshold is a string, FlowRule expects double)\n[\n  {\"resource\": \"hello\", \"grade\": 1, \"count\": \"5\"}\n]\n\n// after (fixed)\n[\n  {\"resource\": \"hello\", \"grade\": 1, \"count\": 5}\n]","handlingStrategy":"try-catch","validationCode":"// Before pushing rules to the datasource, validate each element\n// matches the target rule class schema using a test ObjectMapper\nObjectMapper mapper = new ObjectMapper();\ntry {\n    List<Map<String, Object>> rules = mapper.readValue(ruleJson,\n        new TypeReference<List<Map<String, Object>>>() {});\n    for (Map<String, Object> rule : rules) {\n        mapper.readValue(mapper.writeValueAsString(rule), FlowRule.class);\n    }\n} catch (Exception e) {\n    log.error(\"Rule validation failed: {}\", e.getMessage());\n}","typeGuard":null,"tryCatchPattern":"// Wrap rule loading in a try-catch at the application level\ntry {\n    // load or refresh Sentinel rules from datasource\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"sentinel rule convert error\")) {\n        log.error(\"Sentinel rule conversion failed — check rule JSON format: {}\",\n            e.getMessage());\n        // Do not let bad rules crash the app — log and continue with existing rules\n    } else {\n        throw e;\n    }\n}","preventionTips":["Validate rule JSON against the rule class schema before publishing to the datasource (Nacos, file, etc.).","Use strict Jackson deserialization in a test to catch schema mismatches during CI.","Keep rule data version-aligned with the Sentinel SDK version in your dependencies.","Log the raw rule source string when conversion fails to aid debugging."],"tags":["sentinel","converter","jackson","json","rule-parsing","deserialization"],"backgroundTag":null,"analyzedSha":"115d5901102009492e05d5ec18c3f79cad4077d0","analyzedAt":"2026-08-14T04:47:13.900Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}