databendlabs/databend · error
transfer target page index is out of bounds
Error message
transfer target page index is out of bounds
What it means
Same commit() path as the payload-index panic, but here the target payload exists and payload.pages.get_mut(page_index) returns None: the recorded page index is out of bounds for the destination payload's pages. It indicates the state transfer offsets were recorded against pages that no longer exist.
Solutions
- Ensure pages of the target payload are not freed/compacted between recording transfer offsets and calling commit.
- Validate page_index < payload.pages.len() when recording the offset to fail fast with context.
- Recompute the transfer offsets from the current arena state instead of reusing stale records.
- Report the failing query plan; this is an internal invariant violation.
Defensive patterns
Strategy: validation
Validate before calling
assert!(page_index < payload.pages.len(), "transfer offset references invalid page {}", page_index); Prevention
- Keep target payload pages alive until commit completes
- Recompute transfer offsets after any arena restructuring
- Fail fast at record time with contextual asserts
When it happens
Trigger: commit_transferred_state_offsets committing an offset whose page_index >= payload.pages.len() for the target payload — e.g. pages evicted/compacted after offsets were recorded.
Common situations: Aggregate state transfer across payload arenas during multi-phase aggregation (partial → final) where page allocation or recycling changes between recording and commit.
Related errors
- transfer target payload index is out of bounds
- PartitionItem::BucketSpilled(_) => unreachable!()
- AggregateMeta does not support exchanging between multiple…
- _ => unreachable!()
- not implemented
AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11).
Data as JSON: /api/errors/6bea1c765adf1ebe.
Report an issue: GitHub.
Appendix: source
Thrown at src/query/expression/src/aggregate/payload.rs:100
impl PayloadTransferStateOffsets {
fn record(&mut self, payload_index: usize, offsets: Vec<(usize, usize)>) {
self.offsets.extend(
offsets
.into_iter()
.map(|(page_index, offset)| (payload_index, page_index, offset)),
);
}
fn commit(self, payloads: &mut [Payload]) {
for (payload_index, page_index, offset) in self.offsets {
let payload = payloads
.get_mut(payload_index)
.expect("transfer target payload index is out of bounds");
let page = payload
.pages
.get_mut(page_index)
.expect("transfer target page index is out of bounds");
let next_state_offsets = page
.state_offsets
.checked_add(offset)
.expect("transfer target state offsets overflow");
let initialized_states = page
.rows
.checked_mul(payload.aggrs.len())
.expect("transfer target initialized states overflow");
assert!(
next_state_offsets <= initialized_states,
"transfer target state offsets exceed initialized aggregate states"
);
page.state_offsets = next_state_offsets;
}
}
}
View on GitHub (pinned to 288d84d76e)