{"record":{"id":"6ee33af155d6af9c","repo":"juicedata/juicefs","slug":"page-is-already-released","errorCode":null,"errorMessage":"page is already released","messagePattern":"page is already released","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/chunk/page.go","lineNumber":120,"sourceCode":"}\n\nfunc NewPageReader(p *Page) *pageReader {\n\tp.Acquire()\n\treturn &pageReader{p, 0}\n}\n\nfunc (r *pageReader) Read(buf []byte) (int, error) {\n\tn, err := r.ReadAt(buf, int64(r.off))\n\tr.off += n\n\treturn n, err\n}\n\nfunc (r *pageReader) ReadAt(buf []byte, off int64) (int, error) {\n\tif len(buf) == 0 {\n\t\treturn 0, nil\n\t}\n\tif r.p == nil {\n\t\treturn 0, errors.New(\"page is already released\")\n\t}\n\tif int(off) == len(r.p.Data) {\n\t\treturn 0, io.EOF\n\t}\n\tn := copy(buf, r.p.Data[off:])\n\tif n < len(buf) {\n\t\treturn n, io.EOF\n\t}\n\treturn n, nil\n}\n\nfunc (r *pageReader) Close() error {\n\tif r.p != nil {\n\t\tr.p.Release()\n\t\tr.p = nil\n\t}\n\treturn nil\n}","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/chunk/page.go#L102-L138","documentation":"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.","triggerScenarios":"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).","commonSituations":"Concurrent readers holding a pageReader after the owner released the page; retry logic reading a completed upload's page reader a second time.","solutions":["Ensure the page is not released until all readers are done; extend the page's lifetime or take a reference before reading.","Do not reuse a pageReader after release; obtain a new page/reader for subsequent reads.","Check for double-release / early-release in the producer code that hands out the reader (e.g. in upload completion paths)."],"exampleFix":"// before\nr.p.Release()\nn, err := r.ReadAt(buf, 0) // error: page is already released\n// after\nn, err := r.ReadAt(buf, 0)\nr.p.Release()","handlingStrategy":"type-guard","validationCode":"func canRead(r *chunk.PageReader) bool { return r != nil && !r.Released() } // if such an accessor exists; otherwise track release in owner code","typeGuard":"func (r *pageReader) usable() bool { return r.p != nil }","tryCatchPattern":"n, err := pr.ReadAt(buf, off)\nif err != nil && err.Error() == \"page is already released\" {\n\treturn ErrPageReleased // propagate to owner to re-acquire page\n}","preventionTips":["Release pages only after all ReadAt/Read calls finish","Avoid sharing pageReader across goroutines after release","Acquire a page reference before handing a reader to another component"],"tags":["memory","lifecycle","page"],"backgroundTag":"invalid-state-transition","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}