{"record":{"id":"8f157e184bf27da6","repo":"apache/flink","slug":"other-memory-segment-has-been-freed","errorCode":null,"errorMessage":"other memory segment has been freed.","messagePattern":"other memory segment has been freed\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java","lineNumber":1590,"sourceCode":"            final long thisPos = this.address + offset1;\n            final long otherPos = seg2.address + offset2;\n\n            if (thisPos <= this.addressLimit - len && otherPos <= seg2.addressLimit - len) {\n                // this -> temp buffer\n                UNSAFE.copyMemory(\n                        this.heapMemory, thisPos, tempBuffer, BYTE_ARRAY_BASE_OFFSET, len);\n\n                // other -> this\n                UNSAFE.copyMemory(seg2.heapMemory, otherPos, this.heapMemory, thisPos, len);\n\n                // temp buffer -> other\n                UNSAFE.copyMemory(\n                        tempBuffer, BYTE_ARRAY_BASE_OFFSET, seg2.heapMemory, otherPos, len);\n                return;\n            } else if (this.address > this.addressLimit) {\n                throw new IllegalStateException(\"this memory segment has been freed.\");\n            } else if (seg2.address > seg2.addressLimit) {\n                throw new IllegalStateException(\"other memory segment has been freed.\");\n            }\n        }\n\n        // index is in fact invalid\n        throw new IndexOutOfBoundsException(\n                String.format(\n                        \"offset1=%d, offset2=%d, len=%d, bufferSize=%d, address1=%d, address2=%d\",\n                        offset1, offset2, len, tempBuffer.length, this.address, seg2.address));\n    }\n\n    /**\n     * Equals two memory segment regions.\n     *\n     * @param seg2 Segment to equal this segment with\n     * @param offset1 Offset of this segment to start equaling\n     * @param offset2 Offset of seg2 to start equaling\n     * @param length Length of the equaled memory region\n     * @return true if equal, false otherwise","sourceCodeStart":1572,"sourceCodeEnd":1608,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/core/memory/MemorySegment.java#L1572-L1608","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\na.swapBytes(b, tempBuf, off1, off2, len); // 'other ... has been freed.' => b is freed\n\n// after\nif (b.isFreed()) {\n    throw new IllegalStateException(\"argument segment already released\");\n}\na.swapBytes(b, tempBuf, off1, off2, len);","handlingStrategy":"validation","validationCode":"if (seg2.isFreed()) {\n    throw new IllegalStateException(\"argument segment already freed\");\n}\nseg1.swapBytes(seg2, tempBuf, off1, off2, len);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remove segments from swap indices at release time instead of leaving stale references.","Check both segments' isFreed() in debug assertions around sort loops."],"tags":["memory","lifecycle","flink-core","use-after-free"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}