Hmbown/CodeWhale · error

overwrite

Error message

overwrite

What it means

Test panic from `second.store(&path).expect("overwrite")`: the second, in-place overwrite of the update-check cache failed. store writes to a `.json.tmp` sibling and renames over the existing file, so an overwrite failure means the temp write or the rename over the existing file errored — the atomic-replace path, not first-time creation.

Solutions

  1. Check for and remove a stale `path.with_extension("json.tmp")` before storing, since a leftover temp file can interfere.
  2. Confirm the filesystem supports rename-over-existing atomically; prefer a local tmpfs for tests if running on NFS.
  3. Inspect the anyhow context on the Err to see whether fs::write of the temp file or the rename step failed, and fix the underlying cause (permissions, locks, space).

Example fix

// before
second.store(&path).expect("overwrite");
// after — tolerate or clean a stale temp file from a previous crashed run
let tmp = path.with_extension("json.tmp");
let _ = std::fs::remove_file(&tmp);
second.store(&path).expect("overwrite");
Defensive patterns

Strategy: fallback

Validate before calling

// clear a stale temp file that can block the overwrite
let tmp = path.with_extension("json.tmp");
if tmp.exists() { let _ = std::fs::remove_file(&tmp); }

Type guard

fn can_replace(p: &Path) -> bool {
    p.parent().map(|d| writable_dir(d)).unwrap_or(false)
}
fn writable_dir(p: &Path) -> bool {
    p.metadata().map(|m| !m.permissions().readonly()).unwrap_or(false)
}

Try / catch

match second.store(&path) {
    Ok(()) => {},
    Err(e) => eprintln!("cache overwrite failed, continuing without cache: {e:#}"),
}

Prevention

When it happens

Trigger: Calling store on a path where the target file already exists and the rename fails (file locked by another process, permission change after the first store, filesystem without atomic rename-over support, or the stale json.tmp left by a crashed run blocking the write).

Common situations: Tests run on network mounts (NFS/SMB) with unreliable rename-over-existing; leftover .json.tmp files from interrupted runs on shared TMPDIRs; concurrent test runs writing the same cache path.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/8a7f76b9d4a446ca. Report an issue: GitHub.

Appendix: source

Thrown at crates/release/src/check.rs:233

    #[test]
    fn store_then_load_round_trips_and_survives_an_existing_file() {
        let dir = tempfile::tempdir().expect("tempdir");
        let path = cache_path_in(dir.path());
        assert_eq!(path.file_name().unwrap(), UPDATE_CHECK_CACHE_FILE);

        let first = UpdateCheckCache {
            checked_at_unix: 42,
            latest_tag: Some("v0.9.5".to_string()),
        };
        first.store(&path).expect("store");
        assert_eq!(UpdateCheckCache::load(&path), Some(first));

        // Overwriting in place must not leave the temp file behind.
        let second = UpdateCheckCache {
            checked_at_unix: 99,
            latest_tag: None,
        };
        second.store(&path).expect("overwrite");
        assert_eq!(UpdateCheckCache::load(&path), Some(second));
        assert!(!path.with_extension("json.tmp").exists());
    }

    #[test]
    fn store_creates_a_missing_home_directory() {
        let dir = tempfile::tempdir().expect("tempdir");
        let path = cache_path_in(&dir.path().join("nested").join("home"));
        UpdateCheckCache::now(Some("v1.0.0".to_string()))
            .store(&path)
            .expect("store into a fresh directory");
        assert!(path.exists());
    }

    #[test]
    fn a_corrupt_or_absent_cache_reads_as_none() {
        let dir = tempfile::tempdir().expect("tempdir");
        let path = cache_path_in(dir.path());

View on GitHub (pinned to 433685b202)