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
- Retry the command — transient network-filesystem errors often resolve.
- Check disk space and quota on the cache volume.
- Move the cache to local disk (XDG_CACHE_HOME or Pulumi cache config) to avoid NFS/SMB close errors.
- 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
- Place the pulumi cache on local persistent storage, not NFS/SMB.
- Retry transient I-O failures once before investigating.
- Keep adequate disk headroom to avoid close-time ENOSPC.
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
- writing temp file: %w
- reading environment definition: %w
- creating cache dir: %w
- creating temp file: %w
- acquiring cache lock: %w
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/abc39e9cda5bbb26.
Report an issue: GitHub.