{"record":{"id":"e3008d5bc5a64de4","repo":"apache/skywalking","slug":"load-meter-analyzer-configs-failed","errorCode":null,"errorMessage":"Load meter analyzer configs failed","messagePattern":"Load meter analyzer configs failed","errorType":"exception","errorClass":"ModuleStartException","httpStatus":null,"severity":"error","filePath":"oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleProvider.java","lineNumber":166,"sourceCode":"     * {@link Rules} loader the otel catalog uses, so meter rules participate in\n     * {@code RuleSetMerger} (runtime-rule DB overrides win over disk) and land in\n     * {@code StaticRuleRegistry} (which is what makes {@code /runtime/rule/list},\n     * {@code /inactivate} and revert-to-bundled see a shipped meter rule at all).\n     *\n     * <p>Runs in {@code start()} rather than {@code prepare()} — the merge consults the\n     * runtime-rule override resolver, which needs a live storage module. This mirrors\n     * {@code OpenTelemetryMetricRequestProcessor.start()}.\n     */\n    private List<Rule> loadMeterRules() throws ModuleStartException {\n        final List<String> activeFiles = moduleConfig.meterAnalyzerActiveFileNames();\n        // Null when meterAnalyzerActiveFiles is unset; Rules.loadRules would NPE on it.\n        if (CollectionUtils.isEmpty(activeFiles)) {\n            return Collections.emptyList();\n        }\n        try {\n            return Rules.loadRules(moduleConfig.getConfigPath(), activeFiles);\n        } catch (IOException e) {\n            throw new ModuleStartException(\"Load meter analyzer configs failed\", e);\n        }\n    }\n\n    @Override\n    public void notifyAfterCompleted() {\n\n    }\n\n    @Override\n    public String[] requiredModules() {\n        return new String[] {\n            TelemetryModule.NAME,\n            CoreModule.NAME,\n            ConfigurationModule.NAME,\n            // StorageModule is declared so Storage.start() (which registers the\n            // runtime_rule management table) runs before this provider's start(),\n            // guaranteeing the RuntimeRuleOverrideResolver's DB-backed resolver can load\n            // while loadMeterRules() registers the static meter rules. Without this dep","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleProvider.java#L148-L184","documentation":"Thrown by Layer.registerDynamic(String,int,boolean) when the requested ordinal is below RUNTIME_DYNAMIC_MIN_ORDINAL (100_000). The Layer registry partitions the ordinal space into tiers: 0-9_999 for built-in Layer constants, 10_000-99_999 for boot-time extensions (layer-extensions.yml, SPI, bundled MAL/LAL layerDefinitions), and 100_000+ for runtime hot-update dynamic layers. registerDynamic is the only channel allowed to add layers after seal(), so it enforces the dynamic tier boundary to keep operator-managed ordinals from colliding with runtime ones.","triggerScenarios":"A MAL/LAL runtime hot-update rule file with a top-level `layerDefinitions:` block that declares a layer with an ordinal below 100_000 (e.g. `ordinal: 15000`). The runtime-rule loader funnels the entry into Layer.registerDynamic, which rejects it before compilation.","commonSituations":"Copying a layer definition from a boot-time MAL/LAL file (10_000-99_999 range) into a runtime hot-update file; misunderstanding the tier convention documented in the Layer javadoc; upgrading a setup where ordinals were previously unpoliced.","solutions":["Change the ordinal in the runtime rule's layerDefinitions block to a value >= 100000","If the layer is static/operator-managed, move the definition to layer-extensions.yml or a boot-time MAL/LAL file (which use Layer.register and accept the 10_000-99_999 tier)","Pick an unused ordinal >= 100000 and keep it stable across hot-update reloads, since persisted entity IDs reference layer ordinals"],"exampleFix":"# before (runtime hot-update MAL/LAL file)\nlayerDefinitions:\n  - name: MY_LAYER\n    ordinal: 15000\n# after\nlayerDefinitions:\n  - name: MY_LAYER\n    ordinal: 100000","handlingStrategy":"validation","validationCode":"boolean ok = ordinal >= Layer.RUNTIME_DYNAMIC_MIN_ORDINAL;\nif (!ok) throw new IllegalArgumentException(\"use ordinal >= \" + Layer.RUNTIME_DYNAMIC_MIN_ORDINAL);","typeGuard":null,"tryCatchPattern":"catch (IllegalArgumentException e) { log.warn(\"rejected layer definition: {}\", e.getMessage()); /* fix rule source, do not retry */ }","preventionTips":["Allocate dynamic-layer ordinals from a documented range starting at 100000","Keep runtime hot-update layerDefinitions separate from boot-time ones","Never reuse ordinals already persisted in storage"],"tags":["skywalking","oap","layer","configuration","mal","lal"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}