apache/skywalking · error · ApplyException
LAL register failed for rule '{ruleName}' in {sourceName}
Error message
LAL register failed for rule '{ruleName}' in {sourceName} What it means
ApplyException thrown when the per-rule registration loop (factory.addOrReplace) fails for an LAL rule during phase 2 of LalFileApplier.apply. Distinct from the compile error: compilation succeeded, but swapping the compiled rule into the live listener Factory threw — commonly the cross-file collision guard (another LAL file already owns (layer, ruleName)) or an internal registry failure. Unlike the compile case, rules registered before the failure have landed; they are returned in the exception's partial list so the caller can unwind them.
Source
Thrown at oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/apply/LalFileApplier.java:209
t, Collections.emptyList());
}
}
final List<RegisteredRule> registered = new ArrayList<>();
for (final LogFilterListener.Factory.CompiledLAL x : compiled) {
try {
// Cross-file collision guard: if another LAL file already owns (layer,
// ruleName), and we're not the prior holder (which would be a self-replace),
// reject — the registry's uniqueness invariant is per-layer within the
// cluster. Self-replace is safe because Phase 1 already succeeded and
// addOrReplace is the intended atomic takeover.
factory.addOrReplace(x);
registered.add(new RegisteredRule(x.layer, x.ruleName));
} catch (final Throwable t) {
// Roll back registrations made so far AND the layer claims. Rule-registration
// partial state survives in the caller's `partial` list for unwinding.
layerRegistry.rollback(appliedClaims);
throw new ApplyException(
"LAL register failed for rule '" + x.ruleName + "' in " + sourceName,
t, Collections.unmodifiableList(new ArrayList<>(registered)));
}
}
return new Applied(sourceName, Collections.unmodifiableList(registered), ruleLoader,
appliedClaims);
}
/** Split {@code "catalog/name"} → catalog half. Falls back to {@code lal} for bare
* source names (legacy / test callers). */
private static String deriveCatalog(final String sourceName) {
final int idx = sourceName.indexOf('/');
return idx > 0 ? sourceName.substring(0, idx) : "lal";
}
private static String deriveRuleName(final String sourceName) {
final int idx = sourceName.indexOf('/');
return idx > 0 ? sourceName.substring(idx + 1) : sourceName;View on GitHub (pinned to 102af09b4a)
Solutions
- Rename the colliding rule or move it to a different layer so (layer, ruleName) is unique cluster-wide
- If the intent was replacement, apply the update through the SAME source file/key that owns the rule (sourceName keys the registry) rather than a second file
- Delete or update the prior-owning file first, then apply the new one
- If the failure was transient (concurrent peer apply), retry after the cluster settles — the applier already rolled back layer claims and returned the partial set for cleanup
Defensive patterns
Strategy: try-catch
Validate before calling
// Before apply, ensure (layer, ruleName) uniqueness across all installed files
Set<String> owned = enumerateAllInstalledLalKeys(); // layer:name pairs from every file
for (final String k : newFileKeys) if (owned.contains(k) && !sameSourceFile) throw new ClientSideValidationException("collision: " + k); Try / catch
catch (ApplyException e) with 'LAL register failed': unwind the partial registrations named in e.getPartiallyRegistered() via the admin uninstall, then fix the (layer,name) collision and re-apply.
Prevention
- Enforce cluster-wide (layer, ruleName) uniqueness in your rule-authoring checklist
- Always update a rule through the same source file that installed it — sourceName keys the registry
- Serialize concurrent applies across nodes through the elected main
When it happens
Trigger: Hot-updating an LAL file where rule 'X' in layer 'general' is also declared in a DIFFERENT runtime file or a disk-loaded file on a peer — addOrReplace rejects non-self takeover. Also possible when the LogAnalyzer Factory's internal addOrReplace throws for resource reasons (e.g. classloader retire races).
Common situations: Two runtime LAL files declare the same rule name in the same layer (copy-paste duplication); Re-applying a file while a peer OAP node concurrently applied a colliding file; A disk-loaded lal/*.yaml and a runtime rule collide on (layer, name) because the runtime sourceName derived a key equal to the disk twin's
Related errors
- compile_failed
- LAL compile failed for rule '{name}' in {sourceName}
- LAL YAML parsed to empty/malformed — no rules list in {sourc
- LAL YAML parse failure for {sourceName}
- MAL register failed for {sourceName} (partial)
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/321067e2dd521b2d.
Report an issue: GitHub.