{"record":{"id":"8c1e0c7eb068dcb7","repo":"benbjohnson/litestream","slug":"create-temp-meta-file-w","errorCode":null,"errorMessage":"create temp meta file: %w","messagePattern":"create temp meta file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"vfs.go","lineNumber":989,"sourceCode":"\tif err != nil {\n\t\treturn 0, err\n\t}\n\tv, err := strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"parse hydration meta: %w\", err)\n\t}\n\treturn ltx.TXID(v), nil\n}\n\nfunc (h *Hydrator) saveMeta() error {\n\th.mu.Lock()\n\ttxid := h.txid\n\th.mu.Unlock()\n\n\tdir := filepath.Dir(h.metaPath())\n\ttmp, err := os.CreateTemp(dir, \".hydration-meta-*\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create temp meta file: %w\", err)\n\t}\n\ttmpPath := tmp.Name()\n\n\tif _, err := fmt.Fprintf(tmp, \"%d\\n\", txid); err != nil {\n\t\tif closeErr := tmp.Close(); closeErr != nil {\n\t\t\th.logger.Warn(\"failed to close temp meta file during cleanup\", \"error\", closeErr)\n\t\t}\n\t\tif removeErr := os.Remove(tmpPath); removeErr != nil {\n\t\t\th.logger.Warn(\"failed to remove temp meta file during cleanup\", \"error\", removeErr)\n\t\t}\n\t\treturn fmt.Errorf(\"write hydration meta: %w\", err)\n\t}\n\tif err := tmp.Sync(); err != nil {\n\t\tif closeErr := tmp.Close(); closeErr != nil {\n\t\t\th.logger.Warn(\"failed to close temp meta file during cleanup\", \"error\", closeErr)\n\t\t}\n\t\tif removeErr := os.Remove(tmpPath); removeErr != nil {\n\t\t\th.logger.Warn(\"failed to remove temp meta file during cleanup\", \"error\", removeErr)","sourceCodeStart":971,"sourceCodeEnd":1007,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/vfs.go#L971-L1007","documentation":"Hydrator.saveMeta wraps os.CreateTemp failures in the meta file's directory as \"create temp meta file\". saveMeta persists the current TXID atomically by writing a temp file and renaming it; if a temp file cannot be created, the meta save aborts (litestream logs a warning and continues, since hydration resume is best-effort).","triggerScenarios":"Creating .hydration-meta-* in the hydration directory fails because the directory was deleted, is read-only, or lacks write permission; the filesystem is full (temp inode creation can still fail on some systems); path is on a read-only remount.","commonSituations":"Container running as non-root writing to a root-owned directory; hydration path pointing at a read-only volume; the hydration directory removed by a cleaner while litestream runs.","solutions":["Verify the directory containing the hydration file is writable by the litestream user (ls -ld, check uid)","Free disk space / check inode usage (df -i)","Do not point the hydration path at a read-only or ephemeral volume","Note: saveMeta failures only cost hydration-resume on restart — fix the filesystem, restart litestream to re-hydrate"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure the meta directory is writable before opening the VFS\ndir := filepath.Dir(hydrationPath)\nprobe, err := os.CreateTemp(dir, \".probe-*\")\nif err != nil {\n\t// fix permissions/ownership before starting litestream\n} else {\n\tprobe.Close(); os.Remove(probe.Name())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run litestream as a user with write access to the hydration directory","Avoid read-only or noexec-mounted volumes for hydration state","Check df -i for inode exhaustion, not just df -h","Remember this failure only disables resume; replication continues unaffected"],"tags":["filesystem","permissions","temp-file"],"backgroundTag":"file-write-permission-denied","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"}