hashicorp/terraform · error
cannot create temporary file to update credentials
Error message
cannot create temporary file to update credentials: %s
What it means
Thrown when ioutil.TempFile fails to create a scratch file in the same directory as the credentials file. Terraform writes new credentials via a temp-file + atomic rename pattern; the temp file is created in filepath.Split(filename)'s directory so the rename is on the same filesystem. A failure here means the directory itself is not writable or cannot allocate a new entry.
Solutions
- Ensure the credentials directory exists and is writable: `mkdir -p ~/.terraform.d && chmod u+w ~/.terraform.d`.
- Verify HOME is set to a writable location: `echo $HOME` and `touch $HOME/.terraform.d/.write-test`.
- Check disk and inode usage: `df -h <dir>` and `df -i <dir>`.
- If using TF_CLI_CONFIG_FILE, confirm its parent directory is writable and on a writable filesystem.
Example fix
// before: HOME=/readonly, .terraform.d not writable // $ export HOME=/home/$USER // $ mkdir -p $HOME/.terraform.d && chmod 700 $HOME/.terraform.d // after: terraform login creates the temp file and completes the atomic rename
Defensive patterns
Strategy: validation
Validate before calling
func ensureCredsDirWritable(filename string) error {
dir, _ := filepath.Split(filename)
if dir == "" { dir = "." }
fi, err := os.Stat(dir)
if err != nil {
return os.MkdirAll(dir, 0700)
}
if !fi.IsDir() {
return fmt.Errorf("%s is not a directory", dir)
}
probe, err := os.CreateTemp(dir, ".perm-test-*")
if err != nil {
return fmt.Errorf("cannot create files in %s: %w", dir, err)
}
probe.Close(); os.Remove(probe.Name())
return nil
} Prevention
- Ensure HOME / TF_CLI_CONFIG_FILE parent dir exists and is writable before running login.
- In containers, mount a writable volume at $HOME.
- Avoid pointing credentials at a read-only filesystem.
When it happens
Trigger: The credentials directory (e.g. ~/.terraform.d/) does not exist, is read-only, has no free inodes, or the filesystem is mounted read-only. Also when the directory path is invalid (empty, a file, or otherwise).
Common situations: HOME is unset or points somewhere non-writable (CI containers, restricted service accounts); the .terraform.d directory was deleted or chmod'd to 0500 owned by another user; a read-only root filesystem in a hardened container; disk full / out of inodes.
Related errors
- cannot read
- cannot set mode for credentials file
- cannot write to temporary file
- failed to replace with temporary file
- can not get from Terraform backend configuration
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/3373c2c48fe77ce0.
Report an issue: GitHub.
Appendix: source
Thrown at internal/command/cliconfig/credentials.go:400
}
newSrc, err := json.MarshalIndent(raw, "", " ")
if err != nil {
return fmt.Errorf("cannot serialize updated credentials file: %s", err)
}
// Now we'll write our new content over the top of the existing file.
// Because we updated the data structure surgically here we should not
// have disturbed the meaning of any other content in the file, but it
// might have a different JSON layout than before.
// We'll create a new file with a different name first and then rename
// it over the old file in order to make the change as atomically as
// the underlying OS/filesystem will allow.
{
dir, file := filepath.Split(filename)
f, err := ioutil.TempFile(dir, file)
if err != nil {
return fmt.Errorf("cannot create temporary file to update credentials: %s", err)
}
tmpName := f.Name()
moved := false
defer func(f *os.File, name string) {
// Remove the temporary file if it hasn't been moved yet. We're
// ignoring errors here because there's nothing we can do about
// them anyway.
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)View on GitHub (pinned to d32a084675)