GoogleContainerTools/skaffold · error

failed creating Google Cloud Storage cache directory for %q:

Error message

failed creating Google Cloud Storage cache directory for %q: %w

What it means

Skaffold caches remote Google Cloud Storage objects under a per-source hashed subdirectory of the remote cache dir. SyncObjects creates that subdirectory with os.MkdirAll(0700) before gsutil/client downloads into it; if the OS cannot create it, the underlying error (permissions, non-directory in path, disk full, invalid path characters) is wrapped with this message.

Source

Thrown at pkg/skaffold/gcs/gsutil.go:100

		return "", fmt.Errorf("failed determining remote cache directory: %w", err)
	}
	if err := os.MkdirAll(remoteCacheDir, 0700); err != nil {
		return "", fmt.Errorf("failed creating remote cache directory: %w", err)
	}

	sourceDir, err := getPerSourceDir(g)
	if err != nil {
		return "", fmt.Errorf("failed determining Google Cloud Storage remote cache directory for %q: %w", g.Source, err)
	}
	cacheDir := filepath.Join(remoteCacheDir, sourceDir)
	if _, err := os.Stat(cacheDir); os.IsNotExist(err) {
		// If cache doesn't exist and cloning is disabled then we can't move forward.
		if opts.SyncRemoteCache.CloneDisabled() {
			return "", syncDisabledErr(g, cacheDir)
		}
		// The subdirectory needs to exist to work with gsutil.
		if err := os.MkdirAll(cacheDir, 0700); err != nil {
			return "", fmt.Errorf("failed creating Google Cloud Storage cache directory for %q: %w", g.Source, err)
		}
	} else {
		// If sync property is false then skip fetching latest object from remote storage.
		if g.Sync != nil && !*g.Sync {
			return cacheDir, nil
		}
		// If sync is turned off via flag `--sync-remote-cache` then skip fetching latest object from remote storage.
		if opts.SyncRemoteCache.FetchDisabled() {
			return cacheDir, nil
		}
	}

	gcs := GetGCSClient()
	if err := gcs.DownloadRecursive(ctx, g.Source, cacheDir); err != nil {
		return "", fmt.Errorf("failed to cache Google Cloud Storage objects from %q: %w", g.Source, err)
	}
	return cacheDir, nil
}

View on GitHub (pinned to a1189de023)

Solutions

  1. Check permissions on the remote cache directory (default under ~/.config/skaffold) and the failing subdirectory; chown/chmod so the current user can write (0700).
  2. If a regular file occupies the cacheDir path, delete it so the directory can be recreated.
  3. Set a writable custom cache location via --remote-cache-dir, or free disk space if the disk is full.
  4. Clear the entire remote cache directory and re-run so skaffold recreates it from scratch.

Example fix

# before
$ ls -l ~/.config/skaffold/cache/remote
-rw-r--r-- 1 root root cache-dir   # stale file blocks mkdir
# after
$ sudo rm -rf ~/.config/skaffold/cache/remote/cache-dir
$ sudo chown -R $USER ~/.config/skaffold/cache/remote
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(cacheDir); err == nil {
    if info, ok := err.(nil); !ok { /* stat succeeded */ }
}
// pre-check writability of the parent cache dir before calling SyncObjects
if fi, err := os.Stat(parentDir); err != nil || !fi.IsDir() || fi.Mode().Perm()&0200 == 0 {
    return fmt.Errorf("cache dir %s not writable: %v", parentDir, err)
}

Type guard

func isPathError(err error) (*os.PathError, bool) {
    var pe *os.PathError
    if errors.As(err, &pe) {
        return pe, true
    }
    return nil, false
}

Try / catch

cacheDir, err := gcs.SyncObjects(ctx, gcsInfo, opts)
if err != nil {
    var pe *os.PathError
    if errors.As(err, &pe) && os.IsPermission(pe.Err) {
        log.Warnf("fix permissions on %s: %v", pe.Path, pe.Err)
        return retryWithNewCacheDir(ctx, "--remote-cache-dir", "/tmp/skaffold-cache")
    }
    return err
}

Prevention

When it happens

Trigger: Calling SyncObjects (directly or via cacheGCSObject) for a GCS source whose cache subdirectory does not exist, while os.MkdirAll(cacheDir, 0700) fails — e.g. parent remote cache dir is read-only, a file exists where the directory should be, or the path is invalid.

Common situations: Running skaffold as a non-root user against a cache dir created by root; ~/.config/skaffold or a custom --remote-cache-dir on a read-only mount or full disk; stale cache dir replaced by a regular file; NFS/CI containers with restrictive umasks.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/127cc8df7ca43f29. Report an issue: GitHub.