{"record":{"id":"af8a7f37424ac5a5","repo":"apache/skywalking","slug":"lal-rule-declares-outputtype-but-neither","errorCode":null,"errorMessage":"LAL rule '{}' declares outputType '{}' but neither a registered LALOutputBuilder name nor a class was found.","messagePattern":"LAL rule '(.+?)' declares outputType '(.+?)' but neither a registered LALOutputBuilder name nor a class was found\\.","errorType":"exception","errorClass":"ModuleStartException","httpStatus":null,"severity":"critical","filePath":"oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/provider/log/listener/LogFilterListener.java","lineNumber":545,"sourceCode":"\n        private static Class<?> resolveOutputType(\n                final LALConfig config,\n                final LALSourceTypeProvider spiProvider) throws ModuleStartException {\n            // Per-rule YAML config takes priority\n            final String yamlType = config.getOutputType();\n            if (yamlType != null && !yamlType.isEmpty()) {\n                // Try short name first (no '.' means it's not a FQCN)\n                if (!yamlType.contains(\".\")) {\n                    final Class<?> byName = loadOutputBuilderNames().get(yamlType);\n                    if (byName != null) {\n                        return byName;\n                    }\n                }\n                // Fall back to FQCN\n                try {\n                    return Class.forName(yamlType);\n                } catch (ClassNotFoundException e) {\n                    throw new ModuleStartException(\n                        \"LAL rule '\" + config.getName() + \"' declares outputType '\"\n                            + yamlType + \"' but neither a registered LALOutputBuilder name\"\n                            + \" nor a class was found.\", e);\n                }\n            }\n            // Fall back to SPI default for the layer\n            if (spiProvider != null) {\n                final Class<?> spiOutput = spiProvider.outputType();\n                if (spiOutput != null) {\n                    return spiOutput;\n                }\n            }\n            return null; // DSL.of() will default to Log.class\n        }\n\n        @Override\n        public LogAnalysisListener create(Layer layer) {\n            // Snapshot the suspended set once so a concurrent suspend/resume can't flip behaviour","sourceCodeStart":527,"sourceCodeEnd":563,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/provider/log/listener/LogFilterListener.java#L527-L563","documentation":"Thrown when a LAL rule's outputType: value cannot be resolved: if it contains no dot it is first treated as a registered LALOutputBuilder short name (discovered via ServiceLoader); otherwise/afterwards it is tried as an FQCN via Class.forName(). When both fail — unknown short name and unloadable class — compilation aborts. outputType selects the AbstractLog subclass the rule's sink builds.","triggerScenarios":"outputType: my-log with no LALOutputBuilder SPI registered under that short name and no class named my-log; an FQCN whose jar is not on the classpath; casing/typo in either form.","commonSituations":"Writing a custom output entity but forgetting the META-INF/services registration for the builder; deploying the rule without the custom output jar; renaming the output class without updating rules.","solutions":["Use the exact registered short name of an LALOutputBuilder SPI implementation (check META-INF/services entries)","Or use the fully-qualified class name of an AbstractLog subclass that is on the classpath","Ship the jar containing the output class/builder into oap-libs","Omit outputType to use the layer's SPI default or the built-in Log output"],"exampleFix":"# before\noutputType: mylog\n\n# after (either form)\noutputType: com.mycompany.log.MyLogOutput","handlingStrategy":"validation","validationCode":"// Pre-deploy outputType resolution mirror:\nClass<?> resolve(String v, Map<String, Class<?>> spiNames) throws Exception {\n    if (!v.contains(\".\")) {\n        Class<?> c = spiNames.get(v);\n        if (c != null) return c;\n    }\n    return Class.forName(v); // throws -> rule would fail at boot\n}","typeGuard":null,"tryCatchPattern":"try {\n    Class<?> out = resolveOutputType(config, spiProvider);\n} catch (ModuleStartException e) {\n    // fix the short name (must match an LALOutputBuilder registration) or use a valid FQCN\n}","preventionTips":["Register custom output builders in META-INF/services and use the exact short name","Ship the output jar with the OAP distribution","Omit outputType to inherit the layer default when unsure"],"tags":["lal","log-analyzer","output-type","spi","classpath"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}