{"record":{"id":"b52670facadd41c9","repo":"apache/skywalking","slug":"hierarchyruleprovider-did-not-produce-a-matcher-fo","errorCode":null,"errorMessage":"HierarchyRuleProvider did not produce a matcher for rule: {entry.getKey()}","messagePattern":"HierarchyRuleProvider did not produce a matcher for rule: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/HierarchyDefinitionService.java","lineNumber":170,"sourceCode":"            // snakeyaml's bean binding discards them, so the rule lines must be read separately.\n            // Same idiom as every other rule loader in the DSL path (Rules, LALConfigs,\n            // ZabbixConfigs): read the bytes once, decode as UTF-8 explicitly.\n            final String yamlText = new String(\n                ResourceUtils.readToStream(\"hierarchy-definition.yml\").readAllBytes(), UTF_8);\n            final Yaml yaml = new Yaml();\n            final Map<String, Map> config = yaml.loadAs(yamlText, Map.class);\n            final Map<String, Map<String, String>> hierarchy = (Map<String, Map<String, String>>) config.get(\"hierarchy\");\n            final Map<String, String> ruleExpressions = (Map<String, String>) config.get(\"auto-matching-rules\");\n            this.layerLevels = (Map<String, Integer>) config.get(\"layer-levels\");\n\n            final Map<String, BiFunction<Service, Service, Boolean>> builtRules = ruleProvider.buildRules(\n                ruleExpressions,\n                DslYamlLineIndex.keyLines(yamlText, \"auto-matching-rules\"));\n\n            this.matchingRules = ruleExpressions.entrySet().stream().map(entry -> {\n                final BiFunction<Service, Service, Boolean> matcher = builtRules.get(entry.getKey());\n                if (matcher == null) {\n                    throw new IllegalStateException(\n                        \"HierarchyRuleProvider did not produce a matcher for rule: \" + entry.getKey());\n                }\n                final MatchingRule matchingRule = new MatchingRule(entry.getKey(), entry.getValue(), matcher);\n                return Map.entry(entry.getKey(), matchingRule);\n            }).collect(toMap(Map.Entry::getKey, Map.Entry::getValue));\n            hierarchy.forEach((layer, lowerLayers) -> {\n                final Map<String, MatchingRule> rules = new HashMap<>();\n                lowerLayers.forEach((lowerLayer, ruleName) -> {\n                    rules.put(lowerLayer, this.matchingRules.get(ruleName));\n                });\n                this.hierarchyDefinition.put(layer, rules);\n            });\n        } catch (IOException e) {\n            throw new UnexpectedException(\"hierarchy-definition.yml not found.\", e);\n        }\n    }\n\n    private void checkLayers() {","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/config/HierarchyDefinitionService.java#L152-L188","documentation":"After HierarchyDefinitionService hands the auto-matching-rules expressions to the HierarchyRuleProvider for compilation, it expects a matcher (BiFunction) for every rule name in the YAML. This IllegalStateException fires when builtRules lacks an entry for a rule — the provider silently skipped compilation (typically an unparseable expression) rather than failing itself.","triggerScenarios":"hierarchy-definition.yml contains an auto-matching-rules entry whose expression the provider cannot compile (bad syntax, unsupported operator, missing expression fields), so the provider returns a map without that key.","commonSituations":"Writing custom hierarchy auto-matching rules with invalid expression syntax; upgrading OAP where the rule grammar changed and old expressions no longer compile; typos in rule expression strings.","solutions":["Check hierarchy-definition.yml's auto-matching-rules block and correct the named rule's expression to the supported grammar (see the provider's rule syntax docs)","Look for a preceding WARN/ERROR log from the rule provider explaining why compilation was skipped","Remove or comment out the offending rule if hierarchy auto-matching for that layer is not needed"],"exampleFix":"# before\nauto-matching-rules:\n  bad-rule: \"service.name ==& 'gateway'\"   # invalid operator\n# after\nauto-matching-rules:\n  gateway-rule: \"service.name == 'gateway'\"","handlingStrategy":"validation","validationCode":"# validate every rule compiles before boot\nSet<String> yamlRules = cfg.get('auto-matching-rules', {}).keySet()\nMap<String, ?> built = ruleProvider.buildRules(cfg.get('auto-matching-rules'), lineIndex)\nassert built.keySet().equals(yamlRules) : \"uncompiled rules: \" + (yamlRules - built.keySet())","typeGuard":null,"tryCatchPattern":"Startup should fail fast (missing matcher means broken config); during development, catch IllegalStateException from the init path and print the offending rule name to pinpoint the YAML line.","preventionTips":["Compile-test hierarchy rules in CI with the same provider version as production","Check provider WARN logs during rule development — skipped compilations log before this throws","Keep rule expressions to the documented grammar; avoid fancy string operators"],"tags":["hierarchy","configuration","yaml","rule-compilation","startup"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}