apache/cassandra · error · IllegalStateException
Cannot create a sharedCopy of a SafeMemory object that has…
Error message
Cannot create a sharedCopy of a SafeMemory object that has already been closed
What it means
SafeMemory's copy constructor calls ref.ensureReleased() when the copy's peer pointer is null but the size is non-zero, meaning the source SafeMemory was already closed (its native memory freed). It throws IllegalStateException to prevent handing out a shared copy of freed off-heap memory. Accessing such memory would otherwise crash the JVM.
Solutions
- Ensure the source SafeMemory is still open before calling sharedCopy(); restructure ownership so closer is the last user
- Call sharedCopy() before the source is closed and manage the copy's lifecycle independently
- Wrap shared copies in try-with-resources and avoid closing shared copies while other copies are live
- Use ref-counted access (the ref() handle) to coordinate close across threads
Example fix
// before
try (SafeMemory mem = acquire()) { sharedHolder.set(mem); } // closed on exit
SafeMemory copy = sharedHolder.get().sharedCopy(); // throws
// after
try (SafeMemory mem = acquire()) { sharedHolder.set(mem.sharedCopy()); }
SafeMemory copy = sharedHolder.get().sharedCopy(); // valid Defensive patterns
Strategy: try-catch
Validate before calling
if (source.isClosed()) throw new IllegalStateException("source already closed"); // or track open state yourself Type guard
boolean usable(SafeMemory m) { return m != null && !m.isClosed(); } Try / catch
try { SafeMemory copy = mem.sharedCopy(); } catch (IllegalStateException e) { /* recreate source or skip */ } Prevention
- Use try-with-resources and never let closed sources escape their scope
- Call sharedCopy() while the source is definitely open
- Centralize SafeMemory ownership in one component that closes last
- Prefer ref.count()/ensureReleased-aware handles for cross-thread sharing
When it happens
Trigger: Calling new SafeMemory(existing) or existing.sharedCopy() after the source SafeMemory has been closed via close() (or try-with-resources exiting its scope).
Common situations: Sharing a SafeMemory across threads where one thread closes it while another still holds a reference; use-after-close in try-with-resources; keeping a copy of a Rebuffer/Memory-managed buffer beyond its owner's lifetime.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Already logging to
- Can not finish joining ring as join sequence has not been…
- Can not finish joining ring, sequence is in an incorrect…
- Can not resume bootstrap as join sequence has not been…
- Can only initialize cluster identifier during epoch
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/ae4c7e910f9995ba.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/io/util/SafeMemory.java:45
public class SafeMemory extends Memory implements SharedCloseable
{
private final Ref<?> ref;
public SafeMemory(long size)
{
super(size);
ref = new Ref<>(null, new MemoryTidy(peer, size));
}
private SafeMemory(SafeMemory copyOf)
{
super(copyOf);
ref = copyOf.ref.ref();
/** see {@link Memory#Memory(long)} re: null pointers*/
if (peer == 0 && size != 0)
{
ref.ensureReleased();
throw new IllegalStateException("Cannot create a sharedCopy of a SafeMemory object that has already been closed");
}
}
public SafeMemory sharedCopy()
{
return new SafeMemory(this);
}
public void free()
{
ref.release();
peer = 0;
}
public void close()
{
ref.ensureReleased();
peer = 0;View on GitHub (pinned to 88fd0f6a0e)