Code review comment: I didn't rollback the lastBuffer's writer Index either here (in case it has been written) :(

Code under review:
public int append(byte[] bytes, int off, int len) {
        int alreadyWritten = 0;
        if (minChunkSize > 0) {
            var lastBuffer = lastBuffer();
            if (lastBuffer != null) {
                int availableOnLast = lastBuffer.writableBytes();
                if (availableOnLast > 0) {
                    int toWrite = Math.min(len, availableOnLast);
                    lastBuffer.writeBytes(bytes, off, toWrite);
                    size += toWrite;
                    len -= toWrite;
                    
                    if (len == 0) {
                        return toWrite;
                    }
                    off += toWrite;
                    alreadyWritten = toWrite;
                }
            }
        }
        final int availableCapacity = capacity - size;
        if (availableCapacity == 0) {
            return alreadyWritten;
        }
        
        int toWrite = Math.min(len, availableCapacity);
        final int chunkCapacity;
        if (minChunkSize > 0) {
            
            chunkCapacity = Math.min(Math.max(minChunkSize, toWrite), availableCapacity);
        } else {
            chunkCapacity = toWrite;
        }
        var tmpBuf = allocator.directBuffer(chunkCapacity);
        tmpBuf.writeBytes(bytes, off, toWrite);
        if (buffer == null) {
            buffer = tmpBuf;
        } else {
            boolean newQ = false;
            try {
                if (otherBuffers == null) {
                    otherBuffers = new ArrayDeque<>();
                    newQ = true;
                }
                otherBuffers.add(tmpBuf);
            } catch (Throwable t) {
                
                if (newQ) {
                    otherBuffers = null;
                }
                size -= alreadyWritten;
                tmpBuf.release();
                throw t;
            }
        }
        size += toWrite;
        return toWrite + alreadyWritten;
    }

Line commented on: tmpBuf.release();

Revised code:
public int append(byte[] bytes, int off, int len) {
        Objects.requireNonNull(bytes);
        if (len == 0) {
            return 0;
        }
        int alreadyWritten = 0;
        if (minChunkSize > 0) {
            var lastBuffer = lastBuffer();
            if (lastBuffer != null) {
                int availableOnLast = lastBuffer.writableBytes();
                if (availableOnLast > 0) {
                    int toWrite = Math.min(len, availableOnLast);
                    lastBuffer.writeBytes(bytes, off, toWrite);
                    size += toWrite;
                    len -= toWrite;
                    
                    if (len == 0) {
                        return toWrite;
                    }
                    off += toWrite;
                    alreadyWritten = toWrite;
                }
            }
        }
        final int availableCapacity = capacity - size;
        if (availableCapacity == 0) {
            return alreadyWritten;
        }
        
        int toWrite = Math.min(len, availableCapacity);
        assert toWrite > 0;
        final int chunkCapacity;
        if (minChunkSize > 0) {
            
            chunkCapacity = Math.min(Math.max(minChunkSize, toWrite), availableCapacity);
        } else {
            chunkCapacity = toWrite;
        }
        var tmpBuf = allocator.directBuffer(chunkCapacity);
        try {
            tmpBuf.writeBytes(bytes, off, toWrite);
        } catch (Throwable t) {
            tmpBuf.release();
            throw t;
        }
        if (buffer == null) {
            buffer = tmpBuf;
        } else {
            boolean resetOthers = false;
            try {
                if (otherBuffers == null) {
                    otherBuffers = new ArrayDeque<>();
                    resetOthers = true;
                }
                otherBuffers.add(tmpBuf);
            } catch (Throwable t) {
                rollback(alreadyWritten, tmpBuf, resetOthers);
                throw t;
            }
        }
        size += toWrite;
        return toWrite + alreadyWritten;
    }