apache/skywalking · error · IllegalArgumentException
Hierarchy rule parsing failed: {errors} in expression: {expr
Error message
Hierarchy rule parsing failed: {errors} in expression: {expression} What it means
Thrown by Layer.registerDynamic when a different layer name already occupies the requested ordinal. Ordinals are the persisted identity of a layer (storage rows reference the int), so two names on one ordinal are never allowed, even if attributes otherwise match.
Source
Thrown at oap-server/analyzer/hierarchy/src/main/java/org/apache/skywalking/oap/server/core/config/v2/compiler/HierarchyRuleScriptParser.java:66
final HierarchyRuleParser parser = new HierarchyRuleParser(tokens);
final List<String> errors = new ArrayList<>();
parser.removeErrorListeners();
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(final Recognizer<?, ?> recognizer,
final Object offendingSymbol,
final int line,
final int charPositionInLine,
final String msg,
final RecognitionException e) {
errors.add(line + ":" + charPositionInLine + " " + msg);
}
});
final HierarchyRuleParser.MatchingRuleContext tree = parser.matchingRule();
if (!errors.isEmpty()) {
throw new IllegalArgumentException(
"Hierarchy rule parsing failed: " + String.join("; ", errors)
+ " in expression: " + expression);
}
return new HierarchyRuleModelVisitor().visit(tree);
}
/**
* Visitor that transforms the ANTLR4 parse tree into {@link HierarchyRuleModel}.
*/
private static final class HierarchyRuleModelVisitor
extends HierarchyRuleParserBaseVisitor<HierarchyRuleModel> {
@Override
public HierarchyRuleModel visitMatchingRule(final HierarchyRuleParser.MatchingRuleContext ctx) {
final String upperParam = ctx.param(0).getText();
final String lowerParam = ctx.param(1).getText();
final HierarchyRuleModel.RuleBody body = convertRuleBody(ctx.ruleBody());View on GitHub (pinned to 102af09b4a)
Solutions
- Assign a fresh unused ordinal >= 100000 to the new layer (the error prints the existing owner name)
- If the same layer is intended, reuse the existing name so the idempotent path in registerDynamic returns it
- Keep a documented allocation table for dynamic-layer ordinals to avoid collisions between rule files
Example fix
# before — ordinal 100001 already used by OTHER_LAYER
layerDefinitions:
- name: NEW_LAYER
ordinal: 100001
# after
layerDefinitions:
- name: NEW_LAYER
ordinal: 100002 Defensive patterns
Strategy: validation
Validate before calling
boolean ordinalFree = java.util.Arrays.stream(Layer.values()).noneMatch(l -> l.value() == value);
Prevention
- Maintain an ordinal allocation table per deployment
- When copying a layerDefinitions block, always change both name AND ordinal
When it happens
Trigger: Calling Layer.registerDynamic("NEW_LAYER", 100001, true) when ordinal 100001 belongs to ANOTHER_LAYER. Typical cause: copy-pasting a layerDefinitions entry and changing only the name, keeping the ordinal.
Common situations: Duplicating an existing layer definition block in a runtime MAL/LAL file and forgetting to bump the ordinal; hardcoded ordinal sequences that drift between environments.
Related errors
- Failed to compile hierarchy rule: {name}, expression: {expre
- Load meter analyzer configs failed
- Failed to load GenAI configuration file.
- Output type {outputTypeName} has no setter for field '{field
- Output field '{fieldName}' requires outputType to be set in
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/de3faf776a77e42d.
Report an issue: GitHub.