{"record":{"id":"7eaacc664c8c3bfc","repo":"apache/skywalking","slug":"loganalyzermodule-factory-unavailable-for-lal-comp","errorCode":null,"errorMessage":"LogAnalyzerModule Factory unavailable for LAL compile of {sourceName}","messagePattern":"LogAnalyzerModule Factory unavailable for LAL compile of (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/engine/lal/LalRuleEngine.java","lineNumber":305,"sourceCode":"     * bundle's keys it overwrote are gone — non-overlapping old keys keep serving until\n     * commit removes them. The orchestrator runs the cross-file ownership guard before\n     * calling this; the engine assumes the planned key set is conflict-free.\n     *\n     * <p>Throws {@link RuntimeException} wrapping {@link LalFileApplier.ApplyException} on\n     * compile / register failure; the orchestrator catches and routes to {@link #rollback}.\n     */\n    @Override\n    public CompiledDSL compile(final RuntimeRuleManagementDAO.RuntimeRuleFile file,\n                                  final Classification classification,\n                                  final DSLClassLoaderManager.Kind kind,\n                                  final LalApplyContext ctx) {\n        final String key = DSLScriptKey.key(file.getCatalog(), file.getName());\n        final String sourceName = file.getCatalog() + \"/\" + file.getName();\n        final String newHash = ContentHash\n            .sha256Hex(file.getContent());\n        final LalFileApplier lalApplier = resolveApplier();\n        if (lalApplier == null) {\n            throw new IllegalStateException(\n                \"LogAnalyzerModule Factory unavailable for LAL compile of \" + sourceName);\n        }\n        final LalFileApplier.Applied oldApplied = appliedFor(ctx.getRules(), key);\n        try {\n            final LalFileApplier.Applied newApplied = lalApplier.apply(\n                file.getContent(), sourceName, newHash, kind);\n            return new CompiledLalDSL(file.getCatalog(), file.getName(), newHash, classification,\n                file.getContent(), oldApplied, newApplied);\n        } catch (final LalFileApplier.ApplyException ae) {\n            // Engine-internal partial rollback for the rare case where Phase 2 of\n            // LalFileApplier.apply (the addOrReplace loop) threw after at least one rule was\n            // already swapped. Drop those partial entries so the Factory doesn't carry the\n            // half-applied set forward. The orchestrator never sees a CompiledLalDSL for this\n            // path (we throw EngineCompileException instead of returning), so the orchestrator's\n            // rollback() never runs — meaning the old DSL for any overlap key is NOT restored\n            // by this catch. The state map still points at the old content, so the next\n            // reconciler scan (NO_CHANGE → re-apply on disagreement check) will recover by\n            // recompiling the persisted content. Phase 1 failures arrive here with an empty","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/server-admin/runtime-rule/src/main/java/org/apache/skywalking/oap/server/receiver/runtimerule/engine/lal/LalRuleEngine.java#L287-L323","documentation":"LalRuleEngine.compile throws IllegalStateException when resolveApplier() cannot obtain the LogAnalyzerModule Factory needed to build a LalFileApplier. The runtime-rule engine depends on the log-analyzer module being booted (its Factory is looked up through the module manager); a null result means LogAnalyzerModule is absent or not yet started in this OAP instance. This is a module-dependency wiring error on the node handling the rule compile, surfaced per-file rather than at boot.","triggerScenarios":"A runtime-rule operation targeting a LAL file on an OAP whose configuration excludes the log-analyzer module, or where the module is still initializing when the first compile arrives. Also in custom packagings (e.g. server-tools style boot) that include runtime-rule but not LogAnalyzerModule.","commonSituations":"application.yml trimmed for a metrics-only deployment, dropping log analysis while runtime-rule LAL files remain installed; Module start-order changes making the engine reachable before the Factory registers; Test harnesses booting a subset of modules","solutions":["Enable/start the LogAnalyzerModule in application.yml on every node that will compile LAL runtime rules (check receiver/analyzer module list)","Ensure runtime-rule module declares and waits for its required modules so compiles can't run before the Factory is up","Remove stale LAL runtime-rule files from the store if this deployment intentionally has no log analysis","Restart the node after the config fix; the Factory lookup is not retried lazily"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"final boolean lalReady = moduleManager.find(LogAnalyzerModule.NAME) != null\n    && /* Factory service is registered */ logAnalyzerFactoryAvailable();\nif (!lalReady) deferOrReject(\"LAL compile needs LogAnalyzerModule — enable it first\");","typeGuard":null,"tryCatchPattern":"catch (IllegalStateException e) when 'LogAnalyzerModule Factory unavailable': permanent wiring error on this node — route LAL compiles to a node with log analysis enabled, or enable the module and restart. Do not retry in place.","preventionTips":["Enable LogAnalyzerModule on every node that serves the runtime-rule API in a full deployment","Gate the runtime-rule module's availability on the analyzer modules in packaging configs","In minimal packagings, purge LAL catalog files from the store or disable LAL handling"],"tags":["module-wiring","lal","engine","configuration"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}