{"record":{"id":"fd624a6aaf5ec073","repo":"benbjohnson/litestream","slug":"read-txid-file-w","errorCode":null,"errorMessage":"read txid file: %w","messagePattern":"read txid file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"replica.go","lineNumber":1762,"sourceCode":"\t\treturn fmt.Errorf(\"rename txid file: %w\", err)\n\t}\n\n\tif err := internal.FsyncDir(filepath.Dir(txidPath)); err != nil {\n\t\treturn fmt.Errorf(\"sync txid dir: %w\", err)\n\t}\n\treturn nil\n}\n\n// ReadTXIDFile reads the TXID from a sidecar file at <outputPath>-txid.\n// Returns 0, nil if the file does not exist (first run).\nfunc ReadTXIDFile(outputPath string) (ltx.TXID, error) {\n\ttxidPath := TXIDPath(outputPath)\n\n\tdata, err := os.ReadFile(txidPath)\n\tif os.IsNotExist(err) {\n\t\treturn 0, nil\n\t} else if err != nil {\n\t\treturn 0, fmt.Errorf(\"read txid file: %w\", err)\n\t}\n\n\ttxid, err := ltx.ParseTXID(strings.TrimSpace(string(data)))\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"parse txid file: %w\", err)\n\t}\n\n\treturn txid, nil\n}\n\n// ValidationError represents a single validation issue.\ntype ValidationError struct {\n\tLevel    int           // compaction level\n\tType     string        // \"gap\", \"overlap\", or \"unsorted\"\n\tMessage  string        // human-readable description\n\tPrevFile *ltx.FileInfo // previous file\n\tCurrFile *ltx.FileInfo // current file that caused error\n}","sourceCodeStart":1744,"sourceCodeEnd":1780,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/replica.go#L1744-L1780","documentation":"ReadTXIDFile reads the '<outputPath>-txid' sidecar file to recover the last applied TXID. A missing file is treated as first-run (returns 0, nil), but any other read error is wrapped as 'read txid file: %w'. This indicates the TXID file exists but could not be read, so the replica cannot determine its resume point.","triggerScenarios":"os.ReadFile on '<outputPath>-txid' failing with EACCES (wrong permissions/owner), EISDIR (a directory occupies the path), or device I/O errors — while the file (or same-named directory) exists.","commonSituations":"TXID file created by root but litestream running as another user; leftover directory named 'my.db-txid' from a misconfiguration; corrupted storage; changed umask or container user after an upgrade.","solutions":["Fix permissions on the '<outputPath>-txid' file so the litestream user can read it (chown/chmod)","If the path is a directory or corrupted beyond repair, remove it and let litestream re-create it via a fresh restore/sync","Run litestream as the same user that owns the database and sidecar files","Check device health if dmesg shows I/O errors on the volume"],"exampleFix":"# before\n-rw------- root root my.db-txid   # litestream runs as litestream user\n# after\nchown litestream:litestream my.db-txid && chmod 644 my.db-txid","handlingStrategy":"validation","validationCode":"txidPath := TXIDPath(outputPath)\nif st, err := os.Stat(txidPath); err == nil && st.IsDir() {\n    return fmt.Errorf(\"%s is a directory; remove it\", txidPath)\n}\nif info, err := os.Stat(txidPath); err == nil {\n    f, _ := os.Open(txidPath)\n    defer f.Close()\n    if _, err := f.Read(make([]byte, 1)); err != nil {\n        return fmt.Errorf(\"txid file unreadable: %w\", err)\n    }\n}","typeGuard":"func txidFileReadable(path string) bool {\n    f, err := os.Open(path)\n    if err != nil { return false }\n    defer f.Close()\n    buf := make([]byte, 1)\n    _, err = f.Read(buf)\n    return err == nil\n}","tryCatchPattern":"txid, err := ReadTXIDFile(outputPath)\nif err != nil {\n    if errors.Is(err, os.ErrPermission) {\n        // fix ownership/permissions or run as file owner, then retry\n    }\n    return err\n}","preventionTips":["Run litestream as the same user that owns the database files","Never create files/dirs named '<db>-txid' manually","Standardize the litestream service user across deployments","Check permissions after restores performed as root"],"tags":["filesystem","file-read","permissions","litestream"],"backgroundTag":"file-read-failed","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}