Repository navigation
[TSDB] not all documents with invalid timestamps are redirected to the failure store. #161001
Description
Activity
- added:StorageEngine/Data streamsData streams and their lifecyclesData streams and their lifecycles:StorageEngine/TSDBYou know, for MetricsYou know, for Metrics
on Oct 5, 2026 elasticsearchmachine commented
on Oct 5, 2026 CollaboratorMore actionsPinging @elastic/es-storage-engine (Team:StorageEngine)
elasticsearchmachine commented
on Oct 5, 2026 CollaboratorMore actionsBug analysis
Verdict: Confirmed on
main(6b22cff517be).Root cause: For TSDB data streams,
BulkOperation.groupRequestsByShardsroutes a CREATE by@timestampthroughDataStream#selectTimeSeriesWriteIndex. That method picks the covering backing index by time range only and never checks index blocks. The write block on that older index only fails at the shard (TransportReplicationAction) as aClusterBlockException.BulkOperation#shouldRedirectRequestToFailureStoredeliberately never redirects that exception (case ClusterBlockException err -> false, treated like backpressure), so the client gets a 403. Timestamps with no covering index instead throwDataStream.TimestampErrorduring routing, which is redirected. That explains the asymmetry.Reproduced: Yes. I ran it as a Buildkite fallback because the local JDK was unusable:
TSDBIndexingIT.testDocForWriteBlockedBackingIndexRedirectedToFailureStorefails withindex [.ds-k8s-…-000001] blocked by: [FORBIDDEN/8/index write (api)]. The out-of-range doc in the same test getsfailure_store: used.
Evidence: repro job · scan · candidate fix: TSDBIndexingIT green · scan
Recommended fix:
- In
groupRequestsByShards, aftergetConcreteWriteIndex: if the target is a data stream, the resolved index is not its write index, and it has an index-level WRITE block, throwDataStream.TimestampError(with the block exception as cause). The existing catch then redirects to the failure store. Blocks on the write index and on failure-store requests keep today's no-redirect behaviour. This is incandidate-fix.patch. - Alternative: make
DataStream#getWriteIndex(IndexRequest, …)treat write-blocked backing indices as non-matching. This touches more callers. - Add a
BulkOperationTestsunit test next totestTsdbTimestampErrorDuringRoutingRedirectsToFailureStore.
Risk: Low. This has been the behaviour since 8.19, not a regression. Clients get an explicit 403, so no data is silently lost; it's just a gap in failure-store coverage.
Additional notes
- Reporter:
gmarouli, verified active member ofelastic/elasticsearch-teamvia the GitHub team membership API. - Test layer:
ESSingleNodeTestCase(TSDBIndexingIT). It needs real index-block enforcement, rollover, TSDB time ranges and failure-store creation. ABulkOperationTestsunit test with a mocked shard action could only inject theClusterBlockExceptionby hand, and that case is already asserted as intentional intestFailingDocumentIgnoredByFailureStoreWhenInvalidException. - Repro command:
./gradlew ":modules:data-streams:internalClusterTest" --tests "org.elasticsearch.datastreams.TSDBIndexingIT.testDocForWriteBlockedBackingIndexRedirectedToFailureStore" -Dtests.seed=D844C5615730989E. The test needsMapperExtrasPluginadded togetPlugins()because the failure-store mapping usesmatch_only_text. - Open policy question: should
read_only_allow_delete(disk flood-stage) on an old backing index also redirect? It is closer to backpressure. If not, match onINDEX_WRITE_BLOCK/INDEX_READ_ONLY_BLOCKexplicitly. - Patches
reproduction.patchandcandidate-fix.patchare uploaded as artifacts on the build above.
Generated by bug-analysis · archimedes v0.52.4 · openrouter/anthropic/claude-opus-5.5
After looking at the code and the intention of #148154, I am thinking that the goal was to reject back pressure exceptions only, not any kind of read-only cases. Maybe we should follow here the same advice we gave to logstash and reject only failures that are retryable:
case ClusterBlockException err -> err.retryable() == false;What do you think @lukewhiting ?
We had an offline chat with @gmarouli, @martijnvg and @lukewhiting to discuss this. We agreed that not writing to the failure store on index level blocks (such as read only due to frozen index) was a bug introduced by #148154 being overly broad in the kinds of cluster exceptions it pushed back on the client.
We agreed to move forward with Mary's proposed fix and @lukewhiting will implement and test that.
- added a commit that references this issue
on Oct 6, 2026
Elasticsearch Version
9.3.5, 9.4.1, 9.5.0, main
Installed Plugins
No response
Java Version
bundled
OS Version
n/a
Problem Description
When failure store is enabled and a document with an invalid timestamp, or a timestamp outside of the eligible write window of the time series data stream is indexed and failure store is enabled, the document should be redirected to the failure store. This works correctly, when a document is not matched to any backing index, but it does fail if there is a read-only backing index because it's detected as backpressure. The reproduction path shows how two different documents behave, ideally, they should behave the same way.
Steps to Reproduce
Logs (if relevant)
No response