elastic/elasticsearch · error · IllegalStateException
index [%s] is the write index for data stream [%s] and canno
Error message
index [%s] is the write index for data stream [%s] and cannot be replaced
What it means
IllegalStateException from the downsample 'delete source and add downsample' path when the source backing index is the data stream's current write index. Deleting the write index would orphan the stream's write target, so the operation is refused.
Source
Thrown at modules/data-streams/src/main/java/org/elasticsearch/datastreams/lifecycle/downsampling/DeleteSourceAndAddDownsampleToDS.java:112
"unable find source index [{}] but adding index [{}] to data stream [{}]",
sourceBackingIndex,
downsampleIndex,
dataStreamName
);
ProjectMetadata.Builder newProject = ProjectMetadata.builder(project)
.put(dataStream.addBackingIndex(project, downsampleIndexMeta.getIndex()));
return ClusterState.builder(state).putProjectMetadata(newProject).build();
}
} else {
DataStream sourceParentDataStream = sourceIndexAbstraction.getParentDataStream();
if (sourceParentDataStream != null && sourceParentDataStream.getWriteIndex().getName().equals(sourceBackingIndex)) {
String errorMessage = String.format(
Locale.ROOT,
"index [%s] is the write index for data stream [%s] and cannot be replaced",
sourceBackingIndex,
sourceParentDataStream.getName()
);
throw new IllegalStateException(errorMessage);
}
IndexMetadata sourceIndexMeta = project.index(sourceBackingIndex);
assert sourceIndexMeta != null
: "the source index abstraction exists in the indices lookup, so the index metadata must "
+ "exist in the same cluster state metadata";
// the source index exists so let's start by deleting it
state = MetadataDeleteIndexService.deleteIndices(state.projectState(projectId), Set.of(sourceIndexMeta.getIndex()), settings);
DataStream dataStream = state.metadata().getProject(projectId).dataStreams().get(dataStreamName);
if (sourceParentDataStream != null) {
assert sourceParentDataStream.getName().equals(dataStreamName)
: "the backing index must be part of the provided data "
+ "stream ["
+ dataStreamName
+ "] but it is instead part of data stream ["
+ sourceParentDataStream.getName()
+ "]";
// both indices exist, let's copy the origination date from the source index to the downsample indexView on GitHub (pinned to db6a809a66)
Solutions
- Rollover the data stream first so the target index is no longer the write index
- Target only sealed/non-write backing indices for downsampling
- If deleting was the intent, use the standard index delete API after the index is no longer the write index
Example fix
// before: downsample targets .ds-mylogs-2025-01-01-000001 which is the write index POST mylogs/_rollover POST .ds-mylogs-2025-01-01-000001/_downsample/1h // after: the rolled-over index is no longer the write index and can be downsampled
Defensive patterns
Strategy: validation
Validate before calling
// Never downsample the write index; check before scheduling:
String writeIndex = dataStream.getWriteIndex().getName();
if (writeIndex.equals(targetIndex)) {
rollover(dataStream.getName()); // or skip/pick a different target
} Try / catch
try { downsample(targetIndex); }
catch (IllegalStateException e) {
if (e.getMessage().contains("write index")) { rollover(dsName); downsample(targetIndex); }
else throw e;
} Prevention
- Downsample only indices older than the current write index
- Build a downsample candidate selector that excludes the write index
- Wire rollover into the lifecycle policy so write indices move on schedule
When it happens
Trigger: DeleteSourceAndAddDownsampleToDS is asked to downsample-and-replace an index whose name equals dataStream.getWriteIndex().getName(). The downsample job (or manual delete_backing_index) targeted the live write index instead of a sealed backing index.
Common situations: Running downsampling on the newest backing index without rolling over first; scheduler mis-selecting the write index; manual _modify_data_streams delete_backing_index on the current write index.
Related errors
- Cannot create past TSDB backing index for data stream [{}] b
- Cannot add nodes to test cluster after is has been frozen
- Configuration for {} can not be altered, already locked
- Can not start {}, missing: {}
- Configuration for {} can not be altered, already locked
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/558bcc4119982ef7.
Report an issue: GitHub.