hashicorp/terraform · error
cannot create temporary file to update credentials: %s
Error message
cannot create temporary file to update credentials: %s
What it means
Returned by StoreHostCredentialsEntry (and callers like the credentials helper for `terraform login`/`logout`) when ioutil.TempFile fails while staging an atomic rewrite of the Terraform credentials file (~/.terraform.d/credentials.json). The code intentionally writes to a sibling temp file in the same directory then renames it over the original so a crash never leaves a truncated JSON credentials file. A failure here means Terraform could not even begin that safe write.
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 c9def3e214)
Solutions
- Check that the directory holding the credentials file exists and is writable: `ls -ld ~/.terraform.d` and `touch ~/.terraform.d/.write-test`.
- Ensure HOME (or USERPROFILE on Windows) is set to a real, writable directory inside the container/CI job and export it explicitly.
- Fix ownership if a previous `sudo terraform` created root-owned files: `sudo chown -R $USER ~/.terraform.d`.
- If on a read-only or quota-limited filesystem, point TF_CLI_CONFIG_FILE / TF_DATA_DIR at a writable location or mount a writable volume for credentials.
- Free inodes/disk space on the volume holding the home directory (`df -i`, `df -h`).
Example fix
# before: container launched without a writable HOME docker run --rm -it myimg terraform login # cannot create temporary file to update credentials: open .../credentials.json123456: permission denied # after: give the container a writable home and data dir docker run --rm -it -e HOME=/tmp/tf -v tfdata:/tmp/tf/.terraform.d myimg terraform login
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the credentials directory is writable before calling StoreHostCredentialsEntry
if fi, err := os.Stat(filepath.Dir(credsPath)); err != nil || !fi.IsDir() {
return fmt.Errorf("credentials dir not usable: %w", err)
}
if err := os.WriteFile(filepath.Join(filepath.Dir(credsPath), ".write-probe"), []byte(""), 0600); err != nil {
return fmt.Errorf("credentials dir not writable: %w", err)
}
os.Remove(filepath.Join(filepath.Dir(credsPath), ".write-probe")) Try / catch
// Treat any error from StoreHostCredentialsEntry as a non-fatal credentials failure and continue without persisting the credential (e.g. fall back to env TF_TOKEN_*).
if err := credsStore.StoreHostCredentialsEntry(host, token); err != nil {
if errors.Is(err, fs.ErrPermission) || strings.Contains(err.Error(), "permission denied") {
log.Printf("warning: cannot persist credential for %s (%v); set TF_TOKEN_%s instead", host, err, strings.ReplaceAll(strings.ToUpper(host), ".", "_"))
} else {
return err
}
} Prevention
- Ensure HOME points to a writable, existing directory in containers/CI.
- Never run terraform credentials commands as root unless the home dir is also root-owned.
- Probe the credentials directory for write access during environment setup, not at first login.
- Document TF_CLI_CONFIG_FILE as the escape hatch for read-only home setups.
When it happens
Trigger: ioutil.TempFile(dir, file) at credentials.go:398 returns an error, where dir is the directory portion of the active credentials filename and file is its base name (used as the temp prefix). This happens when the credentials directory does not exist, is not writable by the current user, is on a read-only filesystem, has no free inodes, or the process lacks permission.
Common situations: HOME is unset or points to a non-existent/unwritable directory (common in containers, CI, or hardened sandboxes); the user ran Terraform as root and the .terraform.d directory is now owned by root; a read-only bind-mount of the home directory; an antivirus/EDR agent on Windows blocking temp file creation; an HPC environment with per-user inode quotas exhausted.
Related errors
- cannot write to temporary file %s: %s
- failed to initialize cloudplugin cache directory: %w
- error deleting workspace %s: %w
- cannot read %s: %s
- could not write lock info for %q: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/3373c2c48fe77ce0.
Report an issue: GitHub.