{"record":{"id":"321067e2dd521b2d","repo":"apache/skywalking","slug":"lal-register-failed-for-rule-rulename-in-sour","errorCode":null,"errorMessage":"LAL register failed for rule '{ruleName}' in {sourceName}","messagePattern":"LAL register failed for rule '(.+?)' in (.+?)","errorType":"http","errorClass":"ApplyException","httpStatus":500,"severity":"error","filePath":"oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/apply/LalFileApplier.java","lineNumber":209,"sourceCode":"                    t, Collections.emptyList());\n            }\n        }\n\n        final List<RegisteredRule> registered = new ArrayList<>();\n        for (final LogFilterListener.Factory.CompiledLAL x : compiled) {\n            try {\n                // Cross-file collision guard: if another LAL file already owns (layer,\n                // ruleName), and we're not the prior holder (which would be a self-replace),\n                // reject — the registry's uniqueness invariant is per-layer within the\n                // cluster. Self-replace is safe because Phase 1 already succeeded and\n                // addOrReplace is the intended atomic takeover.\n                factory.addOrReplace(x);\n                registered.add(new RegisteredRule(x.layer, x.ruleName));\n            } catch (final Throwable t) {\n                // Roll back registrations made so far AND the layer claims. Rule-registration\n                // partial state survives in the caller's `partial` list for unwinding.\n                layerRegistry.rollback(appliedClaims);\n                throw new ApplyException(\n                    \"LAL register failed for rule '\" + x.ruleName + \"' in \" + sourceName,\n                    t, Collections.unmodifiableList(new ArrayList<>(registered)));\n            }\n        }\n        return new Applied(sourceName, Collections.unmodifiableList(registered), ruleLoader,\n                           appliedClaims);\n    }\n\n    /** Split {@code \"catalog/name\"} → catalog half. Falls back to {@code lal} for bare\n     *  source names (legacy / test callers). */\n    private static String deriveCatalog(final String sourceName) {\n        final int idx = sourceName.indexOf('/');\n        return idx > 0 ? sourceName.substring(0, idx) : \"lal\";\n    }\n\n    private static String deriveRuleName(final String sourceName) {\n        final int idx = sourceName.indexOf('/');\n        return idx > 0 ? sourceName.substring(idx + 1) : sourceName;","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/apply/LalFileApplier.java#L191-L227","documentation":"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.","triggerScenarios":"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).","commonSituations":"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","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before apply, ensure (layer, ruleName) uniqueness across all installed files\nSet<String> owned = enumerateAllInstalledLalKeys(); // layer:name pairs from every file\nfor (final String k : newFileKeys) if (owned.contains(k) && !sameSourceFile) throw new ClientSideValidationException(\"collision: \" + k);","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["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"],"tags":["lal","registration","collision","runtime-rule"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}