pulumi/pulumi · error

closing temp file: %w

Error message

closing temp file: %w

What it means

writeCachedSpec closes the temp file before renaming it into place; failing close is wrapped as "closing temp file". Close is where buffered write errors surface and on some platforms can also report permission/fs errors. This is rare and usually accompanies a prior write problem.

Source

Thrown at pkg/cmd/pulumi/cloud/spec_fetch.go:142

// writeCachedSpec writes data to path atomically via tempfile + rename. The
// parent directory is created if it doesn't exist.
func writeCachedSpec(path string, data []byte) error {
	if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
		return fmt.Errorf("creating cache dir: %w", err)
	}
	tmp, err := os.CreateTemp(filepath.Dir(path), "spec-*.json.tmp")
	if err != nil {
		return fmt.Errorf("creating temp file: %w", err)
	}
	tmpPath := tmp.Name()
	defer os.Remove(tmpPath)
	if _, err := tmp.Write(data); err != nil {
		tmp.Close()
		return fmt.Errorf("writing temp file: %w", err)
	}
	if err := tmp.Close(); err != nil {
		return fmt.Errorf("closing temp file: %w", err)
	}

	mutex := fsutil.NewFileMutex(path + ".lock")
	if err := mutex.Lock(); err != nil {
		return fmt.Errorf("acquiring cache lock: %w", err)
	}
	defer func() { _ = mutex.Unlock() }()

	//nolint:forbidigo // We acquire a mutex to avoid concurrent writes
	if err := os.Rename(tmpPath, path); err != nil {
		return fmt.Errorf("renaming temp file: %w", err)
	}
	return nil
}

// fetchSpec retrieves the OpenAPI document via Client.GetCloudAPISpec.
func fetchSpec(ctx context.Context, resolved *ResolvedContext) ([]byte, error) {
	body, err := resolved.Client.GetCloudAPISpec(ctx)

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Retry the command — transient network-filesystem errors often resolve.
  2. Check disk space and quota on the cache volume.
  3. Move the cache to local disk (XDG_CACHE_HOME or Pulumi cache config) to avoid NFS/SMB close errors.
  4. If it persists, inspect system logs (dmesg / mount health) for I/O errors on the device.

Example fix

// before
# cache on flaky NFS mount
// after
export XDG_CACHE_HOME=/local/tmp/cache && pulumi api ls
Defensive patterns

Strategy: retry

Validate before calling

// avoid flaky network mounts for the cache
if isNetworkMount(filepath.Dir(path)) {
    os.Setenv("XDG_CACHE_HOME", "/tmp/pulumi-cache")
}

Try / catch

if err := runAPICmd(); err != nil && strings.Contains(err.Error(), "closing temp file") {
    time.Sleep(2 * time.Second)
    return runAPICmd() // transient NFS/I-O errors often clear
}

Prevention

When it happens

Trigger: ensureSpec/seedSpecCache flushing the temp spec file when the filesystem reports errors on fsync/close: ENOSPC on metadata update, stale NFS file handle, or file already deleted underneath the handle.

Common situations: Network filesystems (NFS/EFS/SMB) invalidating handles mid-operation; disk filling between write and close; security agents interfering with file handles.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/abc39e9cda5bbb26. Report an issue: GitHub.