apache/skywalking · error · ApplyException
MAL compile failed for {sourceName}
Error message
MAL compile failed for {sourceName} What it means
ApplyException thrown by MalFileApplier.apply for any phase-1 failure — content parsing/compilation or any pre-register throw that is not PartialRegistrationException. Because the failure happened before MeterSystem registration, the rollback set is deliberately EMPTY: passing a non-empty set would make the caller unregister metrics the still-installed old bundle owns. Layer-registry claims are rolled back first so a failed compile leaks no layer state.
Source
Thrown at oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/apply/MalFileApplier.java:172
convert = new MetricConvert(rule, meterSystem, pool, ruleLoader, storageOpt);
} catch (final MetricConvert.PartialRegistrationException pre) {
// Phase-2 register threw partway. Carry ONLY the subset that actually landed in
// MeterSystem — the caller uses this set for rollback. Passing the full enumerated
// set here would remove metrics the old bundle still owns (disastrous on
// FILTER_ONLY edits, where by definition every metric name is also in the old
// bundle). The layer-registry changes are reverted now so a failed MeterSystem
// register does not leak a half-applied layer state.
layerRegistry.rollback(appliedClaims);
throw new ApplyException(
"MAL register failed for " + sourceName + " (partial)",
pre.getCause() == null ? pre : pre.getCause(),
pre.getRegisteredBeforeFailure());
} catch (final Throwable t) {
// Phase-1 compile failure or other pre-register throw. Nothing was registered with
// MeterSystem, so rollback set is empty — passing a non-empty set would cause the
// caller to unregister metrics the old bundle owns and this apply never touched.
layerRegistry.rollback(appliedClaims);
throw new ApplyException("MAL compile failed for " + sourceName, t, Collections.emptySet());
}
// All DDL for this file's metrics is now fired. If the opt deferred its schema fence
// (batched apply via withSchemaChangeDeferredFence), run the single barrier here so the
// whole file waits ONCE instead of one fence per metric/downsampling. A fence timeout is
// a non-fatal WARN inside the closure; only a barrier transport error throws, which
// aborts this apply exactly as an inline per-resource fence would have.
//
// EXCEPTION: when fenceRunByCaller is set (the runtime-rule REST apply), the orchestrator
// runs the fence itself AFTER the durable commit + peer resume, on a background thread, so
// a long (3-min) cluster-propagation wait neither blocks the apply nor holds peers
// suspended. We only fire the DDL here and leave the closure for the caller to run.
if (!storageOpt.isFenceRunByCaller()) {
try {
storageOpt.runDeferredFence();
} catch (final StorageException e) {
layerRegistry.rollback(appliedClaims);
throw new ApplyException("schema fence failed for " + sourceName, e, metricNames);
}View on GitHub (pinned to 102af09b4a)
Solutions
- Inspect the cause for the exact compile/parse failure and fix the expression or schema
- Pre-validate with the same parse path: Yaml().loadAs(reader, Rule.class) must yield a rule with metricPrefix and metricsRules
- Align the MAL grammar version you author against the running OAP version (check the MAL docs for supported functions)
- Re-apply once fixed; no cleanup is needed because nothing was registered (empty rollback set)
Example fix
# before
exp: increase(total{inventory.recode_type='pod'},5m).scale(0.016666 # typo/truncation
# after
exp: "increase(total{inventory.recode_type='pod'},5m).scale(0.016666)" Defensive patterns
Strategy: try-catch
Validate before calling
try (StringReader r = new StringReader(content)) {
Rule rule = new Yaml().loadAs(r, Rule.class);
if (rule == null || rule.getMetricPrefix() == null || rule.getMetricsRules() == null) reject("incomplete MAL doc");
} Try / catch
catch (ApplyException e) when 'MAL compile failed': rollback set is empty by contract — do NOT unregister anything; fix the compile error from e.getCause() and re-apply fresh.
Prevention
- Pre-compile MAL expressions in CI against the same OAP version
- Validate metricPrefix presence before submit
- Remember phase-1 failures register nothing — cleanup code must not touch the old bundle
When it happens
Trigger: Applying MAL content that fails YAML parse or expression compile: bad exp syntax, missing metricPrefix, unknown MAL function, or metric rule names that fail validation — anything thrown by new MetricConvert(...) before any metric lands in MeterSystem.
Common situations: Invalid expression grammar after editing exp fields; Version skew: MAL functions added in a newer OAP used against an older server; Files missing required top-level keys (metricPrefix) so compile aborts immediately
Related errors
- LAL compile failed for rule '{name}' in {sourceName}
- Failed to compile MAL expression for metric: {}, expression:
- MAL register failed for {sourceName} (partial)
- teardown_deferred
- YAML parse failure for {sourceName}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/79a2956b3e86f179.
Report an issue: GitHub.