{"record":{"id":"c8e08a6ab59802d6","repo":"hashicorp/terraform","slug":"cannot-write-to-temporary-file-s-s","errorCode":null,"errorMessage":"cannot write to temporary file %s: %s","messagePattern":"cannot write to temporary file (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/cliconfig/credentials.go","lineNumber":418,"sourceCode":"\t\t\treturn fmt.Errorf(\"cannot create temporary file to update credentials: %s\", err)\n\t\t}\n\t\ttmpName := f.Name()\n\t\tmoved := false\n\t\tdefer func(f *os.File, name string) {\n\t\t\t// Remove the temporary file if it hasn't been moved yet. We're\n\t\t\t// ignoring errors here because there's nothing we can do about\n\t\t\t// them anyway.\n\t\t\tif !moved {\n\t\t\t\tos.Remove(name)\n\t\t\t}\n\t\t}(f, tmpName)\n\n\t\t// Write the credentials to the temporary file, then immediately close\n\t\t// it, whether or not the write succeeds.\n\t\t_, err = f.Write(newSrc)\n\t\tf.Close()\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"cannot write to temporary file %s: %s\", tmpName, err)\n\t\t}\n\n\t\t// Temporary file now replaces the original file, as atomically as\n\t\t// possible. (At the very least, we should not end up with a file\n\t\t// containing only a partial JSON object.)\n\t\terr = replacefile.AtomicRename(tmpName, filename)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to replace %s with temporary file %s: %s\", filename, tmpName, err)\n\t\t}\n\n\t\t// Credentials file should be readable only by its owner. (This may\n\t\t// not be effective on all platforms, but should at least work on\n\t\t// Unix-like targets and should be harmless elsewhere.)\n\t\tif err := os.Chmod(filename, 0600); err != nil {\n\t\t\treturn fmt.Errorf(\"cannot set mode for credentials file %s: %s\", filename, err)\n\t\t}\n\n\t\tmoved = true","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/command/cliconfig/credentials.go#L400-L436","documentation":"Emitted after the temp file was successfully created (credentials.go:398) but writing the marshaled JSON credential payload to it failed (f.Write at line 415). Because the write is paired with an immediate f.Close and a deferred os.Remove of the temp file, this error leaves the original credentials file untouched — only the throwaway temp file is affected.","triggerScenarios":"f.Write(newSrc) returns a non-nil error. Concrete causes: the filesystem holding the temp file fills up mid-write (ENOSPC), a network filesystem drops the connection (NFS/SMB), the device is quota-limited, an I/O error occurs on the underlying disk, or the temp file was created on a tmpfs that hit its size limit.","commonSituations":"CI runner with a small /tmp or home volume running out of space while logging in; home directory on a network share that flaps; container with an undersized tmpfs mounted at HOME; disk hardware degradation on a long-lived workstation.","solutions":["Free space on the volume that holds the credentials directory (`df -h ~/.terraform.d`) and retry the login/operation.","If the directory is on a flaky network filesystem, move TF_DATA_DIR to local storage and retry.","Check disk health and inode quota (`df -i`); a full inode table also yields write errors even with free bytes.","Re-run `terraform login` (or whichever command triggered the credential write) once space/connectivity is restored — the original file is untouched."],"exampleFix":"# before\n$ terraform login\ncannot write to temporary file /home/me/.terraform.d/credentials429918238: disk quota exceeded\n\n# after\n$ rm -rf ~/.terraform.d/plugin-cache  # free space\n$ quota -s                             # confirm quota\n$ terraform login","handlingStrategy":"try-catch","validationCode":"// Check free space / writability of the credentials directory before persisting\nvar stat unix.Statfs_t\nif err := unix.Statfs(filepath.Dir(credsPath), &stat); err == nil && stat.Bavail == 0 {\n    return errors.New(\"no free space on credentials volume\")\n}","typeGuard":null,"tryCatchPattern":"// Retry once after a transient write (network FS / full disk), then surface a clear error\nif err := credsStore.StoreHostCredentialsEntry(host, token); err != nil {\n    time.Sleep(200 * time.Millisecond)\n    if err2 := credsStore.StoreHostCredentialsEntry(host, token); err2 != nil {\n        return fmt.Errorf(\"persisting credential failed twice (last: %w); original credentials file is intact\", err2)\n    }\n}","preventionTips":["Monitor free space and inode usage on the home/credentials volume.","Avoid network filesystems for the credentials directory; prefer local disk.","In CI, give the home volume enough headroom for credential writes.","Treat a write error as transient-safe: the original file is untouched."],"tags":["filesystem","disk-full","credentials","atomic-write","network-filesystem"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}