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 depView on GitHub (pinned to 102af09b4a)
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
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
- 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
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
- Failed to load GenAI configuration file.
- Failed to compile hierarchy rule: {name}, expression: {expre
- Hierarchy rule parsing failed: {errors} in expression: {expr
- {slot} value '{numText}' exceeds the supported range (must f
- Unclosed interpolation in: {s}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/e3008d5bc5a64de4.
Report an issue: GitHub.