elastic/elasticsearch · error · IllegalStateException

backing index [%s] in tsdb mode doesn't have the [%s] index

Error message

backing index [%s] in tsdb mode doesn't have the [%s] index setting

What it means

Thrown by DataStreamIndexSettingsProvider when computing time-series bounds for an existing (non-migrating) tsdb data stream and the current write index lacks the index.time_series.end_time setting. The provider reads the previous backing index's end time as the new index's start; if that setting is absent it cannot chain the windows and throws IllegalStateException.

Source

Thrown at modules/data-streams/src/main/java/org/elasticsearch/datastreams/DataStreamIndexSettingsProvider.java:123

                indexMode = isMigratingToTimeSeries ? dataStream.getIndexMode() : null;
            } else if (isMigratingToTimeSeries) {
                indexMode = IndexMode.TIME_SERIES;
            } else {
                indexMode = null;
            }
            if (indexMode != null) {
                if (indexMode.isTsdb()) {
                    TimeValue lookAheadTime = DataStreamsPlugin.getLookAheadTime(indexTemplateAndCreateRequestSettings);
                    TimeValue lookBackTime = DataStreamsPlugin.LOOK_BACK_TIME.get(indexTemplateAndCreateRequestSettings);
                    final Instant start;
                    final Instant end;
                    if (dataStream == null || migrating) {
                        start = DataStream.getCanonicalTimestampBound(resolvedAt.minusMillis(lookBackTime.getMillis()));
                        end = DataStream.getCanonicalTimestampBound(resolvedAt.plusMillis(lookAheadTime.getMillis()));
                    } else {
                        IndexMetadata currentLatestBackingIndex = projectMetadata.index(dataStream.getWriteIndex());
                        if (currentLatestBackingIndex.getSettings().hasValue(IndexSettings.TIME_SERIES_END_TIME.getKey()) == false) {
                            throw new IllegalStateException(
                                String.format(
                                    Locale.ROOT,
                                    "backing index [%s] in tsdb mode doesn't have the [%s] index setting",
                                    currentLatestBackingIndex.getIndex().getName(),
                                    IndexSettings.TIME_SERIES_END_TIME.getKey()
                                )
                            );
                        }
                        start = IndexSettings.TIME_SERIES_END_TIME.get(currentLatestBackingIndex.getSettings());
                        if (start.isAfter(resolvedAt)) {
                            end = DataStream.getCanonicalTimestampBound(start.plusMillis(lookAheadTime.getMillis()));
                        } else {
                            end = DataStream.getCanonicalTimestampBound(resolvedAt.plusMillis(lookAheadTime.getMillis()));
                        }
                    }
                    assert start.isBefore(end) : "data stream backing index's start time is not before end time";
                    additionalSettings.put(IndexSettings.TIME_SERIES_START_TIME.getKey(), FORMATTER.format(start));
                    additionalSettings.put(IndexSettings.TIME_SERIES_END_TIME.getKey(), FORMATTER.format(end));

View on GitHub (pinned to db6a809a66)

Solutions

  1. Rollover the data stream so a fresh backing index with correct time_series bounds is created.
  2. Restore or recreate the backing index through the proper tsdb template so index.time_series.end_time is set.
  3. If the index is stale/foreign, remove it from the data stream or reindex into a correctly-created backing index.
Defensive patterns

Strategy: validation

Validate before calling

// Before triggering new backing-index creation, confirm the write index has time_series.end_time.
const settings = await es.indices.getSettings({ index: writeIndex });
const endTime = settings[writeIndex].settings['index.time_series.end_time'];
if (!endTime) {
  throw new Error(`backing index ${writeIndex} missing index.time_series.end_time; rollover first`);
}

Prevention

When it happens

Trigger: A tsdb data stream whose backing index was created without time_series end_time (e.g. created outside the normal tsdb template, restored from an old snapshot, or created before the setting existed), then a new backing index is requested for that data stream.

Common situations: Restoring a tsdb data stream from a snapshot taken on an older version; manually creating a backing index that bypassed index_setting_providers; template drift where the tsdb mode is set but the lifecycle/bounds providers did not run.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/c6195925f3161288. Report an issue: GitHub.