docker/cli · error

error closing temp file

Error message

error closing temp file: %w

What it means

Returned by ConfigFile.Save (config.go:225-227) when closing the temp file fails after writing the marshaled config. Save writes to a temp file in the config dir then atomically renames it over the real config; a close error here is wrapped with this message and aborts the rename, so the original config is preserved.

Solutions

  1. Free disk/inode space on the volume holding the config dir (`df -h`, `df -i`).
  2. Check for filesystem errors or quota limits on the user's home directory.
  3. Retry the operation that triggered the save (e.g. `docker login`) once space is available.
  4. Inspect dmesg/system logs for I/O errors on the underlying device.
Defensive patterns

Strategy: try-catch

Validate before calling

// Fail fast if the target volume is out of space before Save.
if stat, err := os.StatFile(dir); err == nil {
    // caller can check df/stat as appropriate to platform
    _ = stat
}

Try / catch

if err := configFile.Save(); err != nil {
    return fmt.Errorf("could not save docker config (disk full?): %w", err)
}

Prevention

When it happens

Trigger: ConfigFile.Save -> SaveToWriter(temp) succeeds -> temp.Close() returns an error. Causes are filesystem-level: disk full during flush, NFS/quota errors, or the temp file handle being invalidated.

Common situations: The filesystem holding `~/.docker/config.json` runs out of space or inodes mid-write, has a network/NFS hiccup, or imposes a quota. Because Save uses an atomic temp+rename, this error means the write was aborted safely — the existing config.json is not corrupted.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/a5980a36609c6478. Report an issue: GitHub.

Appendix: source

Thrown at cli/config/configfile/file.go:226

		return err
	}
	defer func() {
		// ignore error as the file may already be closed when we reach this.
		_ = temp.Close()
		if retErr != nil {
			if err := os.Remove(temp.Name()); err != nil {
				logrus.WithError(err).WithField("file", temp.Name()).Debug("Error cleaning up temp file")
			}
		}
	}()

	err = c.SaveToWriter(temp)
	if err != nil {
		return err
	}

	if err := temp.Close(); err != nil {
		return fmt.Errorf("error closing temp file: %w", err)
	}

	// Handle situation where the configfile is a symlink, and allow for dangling symlinks
	cfgFile := c.Filename
	if f, err := filepath.EvalSymlinks(cfgFile); err == nil {
		cfgFile = f
	} else if os.IsNotExist(err) {
		// extract the path from the error if the configfile does not exist or is a dangling symlink
		var pathError *os.PathError
		if errors.As(err, &pathError) {
			cfgFile = pathError.Path
		}
	}

	// Try copying the current config file (if any) ownership and permissions
	copyFilePermissions(cfgFile, temp.Name())
	return os.Rename(temp.Name(), cfgFile)
}

View on GitHub (pinned to 4f84911bfe)