apache/cassandra · warning

Failed to close ZstdDictCompress

Error message

Failed to close ZstdDictCompress

What it means

Logged by ZstdCompressionDictionary's Tidyable/Ref tidy method when closing the per-thread ZstdDictCompress native resource throws an exception. The code deliberately swallows the exception and logs a warning so the remaining resources (per-level dicts, decompression dict) still get closed. It signals a native zstd dictionary was not cleanly released, potentially leaking native memory.

Solutions

  1. Treat a single occurrence as benign noise unless accompanied by native memory growth (check Native/ByteBuf memory metrics).
  2. If repeated, verify the zstd JNI/native library version bundled with Cassandra matches the release (no mixed libzstd on the system library path).
  3. Check for concurrent access to the dictionary during close (ensure the dictionary is truly unreferenced; avoid manually dropping refs).
  4. If native memory leaks correlate with these warnings, capture logs and report to the project; restart affected node to reclaim leaked native memory.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    dict.close();
} catch (Exception e) {
    logger.warn("Failed to close ZstdDictCompress", e); // swallow, continue cleanup
}

Prevention

When it happens

Trigger: A compressed sstable's shared compression dictionary is being discarded (table drop, sstable compaction, dictionary replacement) and ZstdDictCompress.close() on the underlying zstd native handle throws; JVM shutdown or cache eviction triggers tidy on a dictionary whose native buffer was already freed or is in use.

Common situations: Table drops with zstd dictionary compression; heavy compaction activity churning dictionaries; native library state inconsistencies after close attempts; monitoring native memory leaks after such warnings.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/d29ede5fa4c11f90. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/compression/ZstdCompressionDictionary.java:281

         * 3. Once refcount is negative, tryRef() returns null, preventing new references
         *
         * Therefore, no synchronization is needed - we have exclusive access to clean up.
         */
        @Override
        public void tidy()
        {
            // Close all compression dictionaries
            // No synchronization needed - reference counting ensures exclusive access
            for (ZstdDictCompress compressDict : zstdDictCompressPerLevel.values())
            {
                try
                {
                    compressDict.close();
                }
                catch (Exception e)
                {
                    // Log but don't fail - continue closing other resources
                    logger.warn("Failed to close ZstdDictCompress", e);
                }
            }
            zstdDictCompressPerLevel.clear();

            // Close decompression dictionary
            ZstdDictDecompress decompressDict = dictDecompress.get();
            if (decompressDict != null)
            {
                try
                {
                    decompressDict.close();
                }
                catch (Exception e)
                {
                    logger.warn("Failed to close ZstdDictDecompress", e);
                }
                dictDecompress.set(null);
            }

View on GitHub (pinned to 88fd0f6a0e)