apache/flink · error · IllegalStateException
other memory segment has been freed.
Error message
other memory segment has been freed.
What it means
In MemorySegment.swapBytes(...), after bounds checking, liveness of both segments is checked in order. If the receiver is alive but the argument seg2 was freed (seg2.address > seg2.addressLimit), it throws IllegalStateException('other memory segment has been freed.') — the error names the second ('other') segment.
Source
Thrown at flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java:1590
final long thisPos = this.address + offset1;
final long otherPos = seg2.address + offset2;
if (thisPos <= this.addressLimit - len && otherPos <= seg2.addressLimit - len) {
// this -> temp buffer
UNSAFE.copyMemory(
this.heapMemory, thisPos, tempBuffer, BYTE_ARRAY_BASE_OFFSET, len);
// other -> this
UNSAFE.copyMemory(seg2.heapMemory, otherPos, this.heapMemory, thisPos, len);
// temp buffer -> other
UNSAFE.copyMemory(
tempBuffer, BYTE_ARRAY_BASE_OFFSET, seg2.heapMemory, otherPos, len);
return;
} else if (this.address > this.addressLimit) {
throw new IllegalStateException("this memory segment has been freed.");
} else if (seg2.address > seg2.addressLimit) {
throw new IllegalStateException("other memory segment has been freed.");
}
}
// index is in fact invalid
throw new IndexOutOfBoundsException(
String.format(
"offset1=%d, offset2=%d, len=%d, bufferSize=%d, address1=%d, address2=%d",
offset1, offset2, len, tempBuffer.length, this.address, seg2.address));
}
/**
* Equals two memory segment regions.
*
* @param seg2 Segment to equal this segment with
* @param offset1 Offset of this segment to start equaling
* @param offset2 Offset of seg2 to start equaling
* @param length Length of the equaled memory region
* @return true if equal, false otherwiseView on GitHub (pinned to 2f3c205e92)
Solutions
- Check seg2.isFreed() (both segments, really) before swapBytes.
- Fix ownership so segments in a sort/index structure are released only after the whole structure is torn down.
- Remove the freed segment from the swap index when it is released, instead of leaving a stale reference.
Example fix
// before
a.swapBytes(b, tempBuf, off1, off2, len); // 'other ... has been freed.' => b is freed
// after
if (b.isFreed()) {
throw new IllegalStateException("argument segment already released");
}
a.swapBytes(b, tempBuf, off1, off2, len); Defensive patterns
Strategy: validation
Validate before calling
if (seg2.isFreed()) {
throw new IllegalStateException("argument segment already freed");
}
seg1.swapBytes(seg2, tempBuf, off1, off2, len); Prevention
- Remove segments from swap indices at release time instead of leaving stale references.
- Check both segments' isFreed() in debug assertions around sort loops.
When it happens
Trigger: Calling swapBytes(a, b, ...) where b was freed earlier — e.g. sorting across segment lists where one segment was released by a spill/cancel path but remains referenced by the index being swapped.
Common situations: Sort buffers spanning multiple segments after partial release; merging spilled runs that reuse segments freed between runs; concurrent cancellation freeing segments still referenced by comparison/swap indices.
Related errors
- segment has been freed
- this memory segment has been freed.
- MemorySegment can be freed only once!
- The runtime context has not been initialized yet. Try access
- Could not write {numBytes} bytes. Buffer overflow.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/8f157e184bf27da6.
Report an issue: GitHub.