apache/skywalking · error · ModuleStartException

Load meter analyzer configs failed

Error message

Load meter analyzer configs failed

What it means

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.

Source

Thrown at oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleProvider.java:166

     * {@link Rules} loader the otel catalog uses, so meter rules participate in
     * {@code RuleSetMerger} (runtime-rule DB overrides win over disk) and land in
     * {@code StaticRuleRegistry} (which is what makes {@code /runtime/rule/list},
     * {@code /inactivate} and revert-to-bundled see a shipped meter rule at all).
     *
     * <p>Runs in {@code start()} rather than {@code prepare()} — the merge consults the
     * runtime-rule override resolver, which needs a live storage module. This mirrors
     * {@code OpenTelemetryMetricRequestProcessor.start()}.
     */
    private List<Rule> loadMeterRules() throws ModuleStartException {
        final List<String> activeFiles = moduleConfig.meterAnalyzerActiveFileNames();
        // Null when meterAnalyzerActiveFiles is unset; Rules.loadRules would NPE on it.
        if (CollectionUtils.isEmpty(activeFiles)) {
            return Collections.emptyList();
        }
        try {
            return Rules.loadRules(moduleConfig.getConfigPath(), activeFiles);
        } catch (IOException e) {
            throw new ModuleStartException("Load meter analyzer configs failed", e);
        }
    }

    @Override
    public void notifyAfterCompleted() {

    }

    @Override
    public String[] requiredModules() {
        return new String[] {
            TelemetryModule.NAME,
            CoreModule.NAME,
            ConfigurationModule.NAME,
            // StorageModule is declared so Storage.start() (which registers the
            // runtime_rule management table) runs before this provider's start(),
            // guaranteeing the RuntimeRuleOverrideResolver's DB-backed resolver can load
            // while loadMeterRules() registers the static meter rules. Without this dep

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Change the ordinal in the runtime rule's layerDefinitions block to a value >= 100000
  2. 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)
  3. Pick an unused ordinal >= 100000 and keep it stable across hot-update reloads, since persisted entity IDs reference layer ordinals

Example fix

# before (runtime hot-update MAL/LAL file)
layerDefinitions:
  - name: MY_LAYER
    ordinal: 15000
# after
layerDefinitions:
  - name: MY_LAYER
    ordinal: 100000
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = ordinal >= Layer.RUNTIME_DYNAMIC_MIN_ORDINAL;
if (!ok) throw new IllegalArgumentException("use ordinal >= " + Layer.RUNTIME_DYNAMIC_MIN_ORDINAL);

Try / catch

catch (IllegalArgumentException e) { log.warn("rejected layer definition: {}", e.getMessage()); /* fix rule source, do not retry */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/e3008d5bc5a64de4. Report an issue: GitHub.