{"record":{"id":"5d10c0a27d409c2f","repo":"benbjohnson/litestream","slug":"close-encoder-w","errorCode":null,"errorMessage":"close encoder: %w","messagePattern":"close encoder: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vfs.go","lineNumber":2170,"sourceCode":"\t\t\t}\n\n\t\t\t// Read page data from buffer file\n\t\t\tbufferOff := dirtyOffsets[pgno]\n\t\t\tdata := make([]byte, pageSize)\n\t\t\tif _, err = bufferFile.ReadAt(data, bufferOff); err != nil {\n\t\t\t\terr = fmt.Errorf(\"read page %d from buffer: %w\", pgno, err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif err = enc.EncodePage(ltx.PageHeader{Pgno: pgno}, data); err != nil {\n\t\t\t\terr = fmt.Errorf(\"encode page %d: %w\", pgno, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// Close encoder (writes trailer and page index)\n\t\tif err = enc.Close(); err != nil {\n\t\t\terr = fmt.Errorf(\"close encoder: %w\", err)\n\t\t\treturn\n\t\t}\n\t}()\n\n\treturn pr\n}\n\n// initWriteBuffer initializes the write buffer file for durability.\n// Any existing buffer content is discarded since unsync'd changes are lost on restart.\n// This function acquires f.mu internally.\nfunc (f *VFSFile) initWriteBuffer() error {\n\tf.mu.Lock()\n\tdefer f.mu.Unlock()\n\treturn f.initWriteBufferWithLock()\n}\n\n// initWriteBufferWithLock initializes the write buffer file for durability.\n// Any existing buffer content is discarded since unsync'd changes are lost on restart.","sourceCodeStart":2152,"sourceCodeEnd":2188,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L2152-L2188","documentation":"Closing the LTX encoder writes the trailer and page index that finalize the immutable LTX file. If enc.Close() fails, the transaction file is incomplete and the sync for that transaction fails with this wrapped error. Because LTX files are immutable and finalized only at close, a failed close means the file must not be used or uploaded.","triggerScenarios":"enc.Close() returns an error after all pages were encoded: final flush to the underlying writer failed (disk full, broken pipe to the uploader), or trailer/index serialization failed.","commonSituations":"Staging disk hitting ENOSPC exactly at trailer time; replica client upload failing on the final chunk; context cancellation just before close; oversized transactions exhausting buffers.","solutions":["Check the wrapped error: ENOSPC → free space on the staging volume; broken pipe → check replica upload connectivity.","Retry the sync; the incomplete LTX file is discarded and the transaction re-encoded.","Ensure graceful shutdown waits for in-flight syncs so Close is not interrupted by cancellation.","Monitor staging volume usage and set alerts before it fills during large transactions."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := db.Sync(ctx); err != nil {\n    if strings.Contains(err.Error(), \"close encoder\") {\n        // incomplete LTX discarded; verify disk/upload then retry\n        return retry.AfterCheck(ctx, db.Sync)\n    }\n    return err\n}","preventionTips":["Alert on staging volume free space — trailers fail at ENOSPC boundary","Wait for in-flight syncs during graceful shutdown","Treat any close-encoder failure as a discarded transaction; never reuse the partial file"],"tags":["go","ltx","encoding","finalization"],"backgroundTag":"file-write-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}