← ClaudeAtlas

atomic-iolisted

Find and fix non-atomic writes to local state files — config, checkpoints, caches, lockfiles — that leave a truncated or corrupted file on disk after a crash, `kill -9`, OOM-kill, power loss, or full disk. Use when the user reports a config/state file that came back empty or unparseable after a crash or forced restart, when reviewing or writing any code that opens a path in write mode (`open(path, 'w')`, `json.dump`, `yaml.safe_dump`, `pickle.dump`, `torch.save`, `.write_text()`) to persist application state a process reads back later, or when the user asks "how do I save this safely" / "make this crash-safe" / "atomic write". Covers the temp-file-fsync-rename fix, directory fsync, single-writer locking, validate-on-read recovery, and Windows-specific EPERM/antivirus-lock retries on rename.
0xmortuex/claude-code-skills · ★ 0 · Data & Documents · score 72
Install: claude install-skill 0xmortuex/claude-code-skills
# atomic-io `open(path, 'w')` truncates the file to zero length the instant it's called, before a single byte of new content lands. Every line between that open and the matching close is a window where a crash, `kill -9`, an OOM-kill, a container eviction, or a plain power loss leaves the file in whatever state it was in when the process died — often empty, sometimes truncated mid-record. This is strictly worse than not writing at all: the previous good version is gone, and the new one never fully arrived. It's the single most common way "unused" config files, job checkpoints, and local caches turn into 3am incidents, and it's easy to miss in review because the code *looks* fine — it reads back correctly in every test that doesn't inject a crash mid-write. The fix is one well-known pattern, not a debate: write to a temp file in the same directory, flush and `fsync` it, then atomically rename it over the target (`os.replace` on POSIX and Windows both — never `os.rename` on Windows, which raises if the destination exists). The rename is what makes this safe: a reader always sees either the fully-old or fully-new file, never a partial one, because rename swaps a directory entry rather than mutating file contents. Skipping the `fsync` before the rename is a common half-fix — without it, the rename can be durable while the data it points to isn't, so a crash right after can expose zero-length or garbage content through the new name. ## What to check for **The write path.** Gre