juicedata/juicefs · error

page is already released

Error message

page is already released

What it means

pageReader.ReadAt reports that the underlying page has already been released (its buffer returned to the pool) and can no longer be read. Reading from a released page would access freed/reused memory, so the reader refuses with this error instead.

Source

Thrown at pkg/chunk/page.go:120

}

func NewPageReader(p *Page) *pageReader {
	p.Acquire()
	return &pageReader{p, 0}
}

func (r *pageReader) Read(buf []byte) (int, error) {
	n, err := r.ReadAt(buf, int64(r.off))
	r.off += n
	return n, err
}

func (r *pageReader) ReadAt(buf []byte, off int64) (int, error) {
	if len(buf) == 0 {
		return 0, nil
	}
	if r.p == nil {
		return 0, errors.New("page is already released")
	}
	if int(off) == len(r.p.Data) {
		return 0, io.EOF
	}
	n := copy(buf, r.p.Data[off:])
	if n < len(buf) {
		return n, io.EOF
	}
	return n, nil
}

func (r *pageReader) Close() error {
	if r.p != nil {
		r.p.Release()
		r.p = nil
	}
	return nil
}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Ensure the page is not released until all readers are done; extend the page's lifetime or take a reference before reading.
  2. Do not reuse a pageReader after release; obtain a new page/reader for subsequent reads.
  3. Check for double-release / early-release in the producer code that hands out the reader (e.g. in upload completion paths).

Example fix

// before
r.p.Release()
n, err := r.ReadAt(buf, 0) // error: page is already released
// after
n, err := r.ReadAt(buf, 0)
r.p.Release()
Defensive patterns

Strategy: type-guard

Validate before calling

func canRead(r *chunk.PageReader) bool { return r != nil && !r.Released() } // if such an accessor exists; otherwise track release in owner code

Type guard

func (r *pageReader) usable() bool { return r.p != nil }

Try / catch

n, err := pr.ReadAt(buf, off)
if err != nil && err.Error() == "page is already released" {
	return ErrPageReleased // propagate to owner to re-acquire page
}

Prevention

When it happens

Trigger: Calling ReadAt (directly or via Read) on a pageReader whose page was released via r.p.Release() / a nil-out on release, or reusing a pageReader after its page lifetime ended (e.g. after an upload finished).

Common situations: Concurrent readers holding a pageReader after the owner released the page; retry logic reading a completed upload's page reader a second time.

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


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/6ee33af155d6af9c. Report an issue: GitHub.