apache/skywalking · critical · ModuleStartException
Metric TTL should be at least 2 days, current value is {}
Error message
Metric TTL should be at least 2 days, current value is {} What it means
ModuleStartException thrown by CoreModuleProvider.start() when core.metrics-data-ttl in application.yml is below 2 days. Metrics data in storage (BanyanDB/ES/...) is rolled up and down-sampled over multi-day windows, so a 0- or 1-day TTL would destroy data before roll-up completes; startup aborts as a guard. The check is a simple int comparison on moduleConfig.getMetricsDataTTL().
Source
Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java:391
this.registerServiceImplementation(OALEngineLoaderService.class, oalEngineLoaderService);
annotationScan.registerListener(new StreamAnnotationListener(getManager()));
if (moduleConfig.isGRPCSslEnabled()) {
this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout(),
moduleConfig.getGRPCSslTrustedCAPath()
);
} else {
this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout());
}
this.registerServiceImplementation(RemoteClientManager.class, remoteClientManager);
// Management
this.registerServiceImplementation(
UITemplateManagementService.class, new UITemplateManagementService(getManager()));
if (moduleConfig.getMetricsDataTTL() < 2) {
throw new ModuleStartException(
"Metric TTL should be at least 2 days, current value is " + moduleConfig.getMetricsDataTTL());
}
setBootingParameter("TTL.metrics", moduleConfig.getMetricsDataTTL());
if (moduleConfig.getRecordDataTTL() < 2) {
throw new ModuleStartException(
"Record TTL should be at least 2 days, current value is " + moduleConfig.getRecordDataTTL());
}
setBootingParameter("TTL.record", moduleConfig.getRecordDataTTL());
final MetricsStreamProcessor metricsStreamProcessor = MetricsStreamProcessor.getInstance();
metricsStreamProcessor.setL1FlushPeriod(moduleConfig.getL1FlushPeriod());
metricsStreamProcessor.setStorageSessionTimeout(moduleConfig.getStorageSessionTimeout());
RecordStreamProcessor.getInstance().setRecordDataTTL(moduleConfig.getRecordDataTTL());
TopNStreamProcessor.getInstance().setTopNWorkerReportCycle(moduleConfig.getTopNReportPeriod());
apdexThresholdConfig = new ApdexThresholdConfig(this);
ApdexMetrics.setDICT(apdexThresholdConfig);
loggingConfigWatcher = new LoggingConfigWatcher(this);
View on GitHub (pinned to 102af09b4a)
Solutions
- Set core.metrics-data-ttl to at least 2 (days): metrics-data-ttl: 7 is the shipped default; use larger values for roll-up retention
- If disk pressure motivated the change, address it via storage retention policies or reduced metric sets instead of TTL < 2
- Validate any env-var substitution produces a number >= 2
- Restart OAP
Example fix
# before core: metrics-data-ttl: 1 # after core: metrics-data-ttl: 7
Defensive patterns
Strategy: validation
Validate before calling
int ttl = Integer.parseInt(System.getenv().getOrDefault("SW_CORE_METRICS_DATA_TTL", "7"));
if (ttl < 2) {
throw new IllegalStateException("core.metrics-data-ttl must be >= 2 days, got " + ttl);
} Prevention
- Add a config-lint rule: metrics-data-ttl >= 2 and record-data-ttl >= 2 in every environment's application.yml
- Remember the unit is DAYS; never set these keys when thinking in hours
- In ephemeral/dev environments, disable unwanted metrics at the source instead of shrinking TTL below the floor
When it happens
Trigger: Setting core.metrics-data-ttl: 0 or 1 (or a placeholder resolving to those) in application.yml. Also triggered by removing the key if a profile/default leaves it below 2 — the provider throws before MetricsStreamProcessor is tuned.
Common situations: Developers shrinking TTLs on local/ephemeral environments to save disk; unit-of-moment confusion (TTL is in DAYS, some assume minutes); overwriting the shipped application.yml with a minimal config that drops the TTL block, leaving a low default.
Related errors
- Record TTL should be at least 2 days, current value is {}
- Zookeeper hostPort cannot be null or empty.
- Zookeeper namespace cannot be null or empty.
- decorate() should be invoked after service()
- Failed to compile MAL expression for metric: {}, expression:
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/b53ac287889905e7.
Report an issue: GitHub.