apache/skywalking · error · IllegalArgumentException

expression can't be empty

Error message

expression can't be empty

What it means

IllegalArgumentException thrown by RulesReader while loading alarm-settings.yml when a `*_rule` entry has an empty or missing `expression` key. Every alarm rule must carry an expression; the reader fails fast during YAML parsing so the OAP does not start (or the dynamic config update fails) with a half-initialized rule set.

Source

Thrown at oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java:105

    }

    /**
     * Read rule config into {@link AlarmRule}
     */
    private void readRulesConfig(Rules rules) {
        Map rulesData = (Map) yamlData.get("rules");
        if (rulesData == null) {
            return;
        }
        rules.setRules(new ArrayList<>());
        rulesData.forEach((k, v) -> {
            if (((String) k).endsWith("_rule")) {
                AlarmRule alarmRule = new AlarmRule(moduleManager);
                alarmRule.setAlarmRuleName((String) k);
                Map settings = (Map) v;
                Object expression = settings.get("expression");
                if (StringUtil.isEmpty((String) expression)) {
                    throw new IllegalArgumentException("expression can't be empty");
                }
                try {
                    alarmRule.setExpression(expression.toString());
                } catch (IllegalExpressionException e) {
                    throw new IllegalArgumentException(e);
                }
                alarmRule.setIncludeNames((ArrayList) settings.getOrDefault("include-names", new ArrayList(0)));
                alarmRule.setExcludeNames((ArrayList) settings.getOrDefault("exclude-names", new ArrayList(0)));
                alarmRule.setIncludeNamesRegex((String) settings.getOrDefault("include-names-regex", ""));
                alarmRule.setExcludeNamesRegex((String) settings.getOrDefault("exclude-names-regex", ""));
                alarmRule.setPeriod((Integer) settings.getOrDefault("period", 1));
                // How many times of checks, the alarm keeps silence after alarm triggered, default as same as period.
                alarmRule.setSilencePeriod((Integer) settings.getOrDefault("silence-period", alarmRule.getPeriod()));
                alarmRule.setRecoveryObservationPeriod((Integer) settings.getOrDefault("recovery-observation-period",
                        0));
                alarmRule.setMessage(
                        (String) settings.getOrDefault("message", "Alarm caused by Rule " + alarmRule
                                .getAlarmRuleName()));

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Add a valid MQE expression to the rule entry, e.g. `expression: sum(service_resp_time > 1000) >= 3`.
  2. Check YAML indentation — `expression` must be a direct child of the rule name, same level as `period`, `threshold`, etc.
  3. If the rule is intentionally disabled, remove or rename the key so it does not end with `_rule` instead of leaving it expression-less.
  4. Validate alarm-settings.yml with a YAML linter before deploying; the exception aborts the entire rules load, not just this rule.

Example fix

# before
rules:
  service_sla_rule:
    threshold: 1
# after
rules:
  service_sla_rule:
    expression: sum(service_sla < 90) >= 3
    threshold: 1
Defensive patterns

Strategy: validation

Validate before calling

# YAML pre-check before deploying alarm-settings.yml
python3 -c "
import yaml,sys
rules = yaml.safe_load(open('alarm-settings.yml')).get('rules') or {}
for name, s in rules.items():
    if name.endswith('_rule') and not (s.get('expression') or '').strip():
        sys.exit(f'{name}: expression missing/empty')
"

Prevention

When it happens

Trigger: A rules map entry whose key ends with `_rule` but whose settings map has no `expression` key, or expression: "" (empty string / null after YAML parsing). RulesReader calls alarmRule.setExpression(expression.toString()) only after StringUtil.isEmpty passes, so any blank value hits this branch.

Common situations: Creating a new rule by copy-paste and deleting the expression line; YAML indentation that accidentally places `expression` under a sibling key; setting expression: null while templating alarm-settings via Helm/Kustomize; a commented-out line (`#expression: ...`) that removes the only expression.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/e53d0e1665dc7d2b. Report an issue: GitHub.