apache/flink · error · IllegalStateException
segment has been freed
Error message
segment has been freed
What it means
Inside wrapInternal, a segment is detected as freed when address > addressLimit (free() deliberately sets address = addressLimit + 1 to poison it). Calling wrap(offset, length) on a freed segment therefore throws IllegalStateException('segment has been freed') before any ByteBuffer can be created.
Source
Thrown at flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java:344
return wrapInternal(offset, length);
}
private ByteBuffer wrapInternal(int offset, int length) {
if (address <= addressLimit) {
if (heapMemory != null) {
return ByteBuffer.wrap(heapMemory, offset, length);
} else {
try {
ByteBuffer wrapper = Preconditions.checkNotNull(offHeapBuffer).duplicate();
wrapper.limit(offset + length);
wrapper.position(offset);
return wrapper;
} catch (IllegalArgumentException e) {
throw new IndexOutOfBoundsException();
}
}
} else {
throw new IllegalStateException("segment has been freed");
}
}
/**
* Gets the owner of this memory segment. Returns null, if the owner was not set.
*
* @return The owner of the memory segment, or null, if it does not have an owner.
*/
@Nullable
public Object getOwner() {
return owner;
}
// ------------------------------------------------------------------------
// Random Access get() and put() methods
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------View on GitHub (pinned to 2f3c205e92)
Solutions
- Check segment.isFreed() before wrapping and abort/skip if freed.
- Fix ownership so nothing touches a segment after free()/recycle — release cached views before recycling the buffer.
- If a ByteBuffer must outlive the segment, copy the bytes into an owned buffer before the segment is freed.
Example fix
// before
ByteBuffer view = segment.wrap(offset, length); // IllegalStateException after free()
// after
if (segment.isFreed()) {
throw new IllegalStateException("buffer already recycled; copy earlier");
}
ByteBuffer view = segment.wrap(offset, length); Defensive patterns
Strategy: validation
Validate before calling
if (segment.isFreed()) {
throw new IllegalStateException("segment already freed; cannot wrap");
}
ByteBuffer view = segment.wrap(offset, length); Prevention
- Never hold a wrapped ByteBuffer past the segment's lifetime — copy if the view must survive.
- Check isFreed() at every wrap site that can race a recycle path.
When it happens
Trigger: Calling wrap() after MemorySegment.free() (or after the owning pool recycled the segment), e.g. retaining a ByteBuffer view beyond the segment's lifetime, or wrapping a buffer that a failed task already released.
Common situations: Caching wrapped ByteBuffers past buffer recycle points in network-stack or sink code; error paths that free segments while other components still hold references; asynchronous writers using a view of memory already returned to the pool.
Related errors
- this memory segment has been freed.
- other 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/85788259cdc8e5ba.
Report an issue: GitHub.