apache/skywalking · error · UnexpectedException
Load rule {} failed
Error message
Load rule {} failed What it means
UnexpectedException ('Load rule X failed') wrapping an IOException raised while a MAL rule's YAML text is being parsed by SnakeYAML (loadAs on a StringReader) inside parseRule. It fires at rule-load time for the named rule; the wrapped cause carries the underlying parse detail.
Source
Thrown at oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/prometheus/rule/Rules.java:168
private static Rule parseRule(final String rulesetDir, final String ruleName,
final String relPath, final byte[] bytes) {
// Decode once and bind from the String: RuleSourceLines re-composes the SAME text to read
// positional marks, which snakeyaml's bean binding discards.
final String text = new String(bytes, StandardCharsets.UTF_8);
try (Reader r = new StringReader(text)) {
Rule rule = new Yaml().loadAs(r, Rule.class);
if (rule == null) {
return null;
}
rule.setName(ruleName);
rule.setSourcePath(rulesetDir + "/"
+ (relPath == null ? ruleName + ".yaml" : relPath));
RuleSourceLines.assign(rule, text);
registerInlineLayers(ruleName, rule);
return rule;
} catch (IOException e) {
throw new UnexpectedException("Load rule " + ruleName + " failed", e);
}
}
/**
* Funnel any inline {@code layerDefinitions:} entries through {@code Layer.register}.
* Conflict checks (reserved-range, name uniqueness, ordinal uniqueness, sealed-state) live
* in {@code Layer.register}; failures here surface with the offending rule name in
* the stack trace.
*/
private static void registerInlineLayers(final String ruleName, final Rule rule) {
final List<LayerDefinition> defs = rule.getLayerDefinitions();
if (defs == null || defs.isEmpty()) {
return;
}
for (final LayerDefinition def : defs) {
try {
def.register();
} catch (RuntimeException e) {View on GitHub (pinned to 102af09b4a)
Solutions
- Open the named rule file and run it through a YAML linter — fix indentation, tabs, and quoting
- If the rule comes from a dynamic/runtime source, re-validate the stored rule text before it is pushed
- Compare against a known-good built-in rule file for structural keys (metric/exp/filter) — wrong key names can also derail parsing
- Restart/reload rules after the fix; rule loading is fail-fast at startup
Example fix
# before metricPrefix: test rule: bad_indent # after metricPrefix: test rule: fixed
Defensive patterns
Strategy: validation
Validate before calling
// CI gate: every rule file must parse as a Rule Rule rule = new Yaml().loadAs(new String(Files.readAllBytes(p), StandardCharsets.UTF_8), Rule.class); assert rule != null && rule.getMetricPrefix() != null;
Try / catch
catch (UnexpectedException e) { /* cause carries the YAML failure; fix the named file and reload */ } Prevention
- Lint all MAL rule YAMLs in CI (yamllint + SnakeYAML loadAs)
- Compare structure against a known-good built-in rule
- Never hand-edit rules on live nodes; change them in source control
When it happens
Trigger: SnakeYAML raising an IOException (in practice usually a wrapped YAML stream problem such as malformed content that surfaces during reader I/O) while parsing the rule body previously read from disk or from a merged/resolver source. The rule name in the message identifies which file failed.
Common situations: Malformed YAML in a custom rule (bad indentation, tabs, unclosed quotes) that manifests during load; rule files rewritten by config-management tooling that truncated them; rules coming from a runtime-rule resolver/DB whose stored bytes are not valid YAML.
Related errors
- {}: one of service(), instance() or endpoint() should be inv
- Failed to compile MAL filter expression: {}
- Load rule file {} failed
- Some configuration files of enabled rules are not found, ena
- MAL rule {} layerDefinitions entry rejected: {}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/01a29b79a95d7030.
Report an issue: GitHub.