hashicorp/terraform · error
failed to replace %s with temporary file %s: %s
Error message
failed to replace %s with temporary file %s: %s
What it means
Thrown when replacefile.AtomicRename fails to atomically move the freshly-written temp file over the real credentials file. AtomicRename performs an OS-level rename (rename(2) on Unix, MoveFileEx with MOVEFILE_REPLACE_EXISTING on Windows); failure means the rename syscall itself failed, not the write.
Source
Thrown at internal/command/cliconfig/credentials.go:426
if !moved {
os.Remove(name)
}
}(f, tmpName)
// Write the credentials to the temporary file, then immediately close
// it, whether or not the write succeeds.
_, err = f.Write(newSrc)
f.Close()
if err != nil {
return fmt.Errorf("cannot write to temporary file %s: %s", tmpName, err)
}
// Temporary file now replaces the original file, as atomically as
// possible. (At the very least, we should not end up with a file
// containing only a partial JSON object.)
err = replacefile.AtomicRename(tmpName, filename)
if err != nil {
return fmt.Errorf("failed to replace %s with temporary file %s: %s", filename, tmpName, err)
}
// Credentials file should be readable only by its owner. (This may
// not be effective on all platforms, but should at least work on
// Unix-like targets and should be harmless elsewhere.)
if err := os.Chmod(filename, 0600); err != nil {
return fmt.Errorf("cannot set mode for credentials file %s: %s", filename, err)
}
moved = true
}
if new != nil {
s.configured[host] = new.ToStore()
} else {
delete(s.configured, host)
}
View on GitHub (pinned to d32a084675)
Solutions
- Close any editor or other Terraform process holding the credentials file open, then retry.
- Ensure the parent directory of the credentials file is writable and on the same filesystem as the temp file (no cross-mount symlink).
- Check SELinux/AppArmor audit logs for denials (`ausearch -m avc` / `dmesg | grep -i denied`).
- On persistent EXDEV, remove symlinks in the credentials path so temp and target share one filesystem.
Defensive patterns
Strategy: try-catch
Try / catch
// Same-filesystem check to pre-empt EXDEV-style rename failures
func sameFS(a, b string) bool {
var sa, sb syscall.Stat_t
if syscall.Stat(a, &sa) != nil { return false }
if syscall.Stat(b, &sb) != nil { return false }
return sa.Dev == sb.Dev
} Prevention
- Keep the credentials temp file and target on the same filesystem (the code already does this if dir is consistent).
- Close the credentials file in other processes before login/logout on Windows.
- Inspect SELinux/AppArmor audit logs when renames fail mysteriously.
When it happens
Trigger: Source and destination are on different filesystems (EXDEV on POSIX — should not happen since temp is created in the same dir, but can if the dir spans a bind mount); destination is a directory or the parent lacks write permission; on Windows the destination is open in another process; SELinux/AppArmor denies the rename.
Common situations: Another Terraform process or editor holds the file open (Windows); a security module blocks cross-context rename; the credentials path was redirected across a mount boundary by a symlink; the parent directory is not writable.
Related errors
- cannot create temporary file to update credentials: %s
- cannot write to temporary file %s: %s
- failed to unlock both S3 and DynamoDB: S3 error: %v, DynamoD
- cannot read %s: %s
- cannot set mode for credentials file %s: %s
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/d9e7fd10ee9c4f78.
Report an issue: GitHub.