GoogleContainerTools/skaffold · error

failed creating remote cache directory: %w

Error message

failed creating remote cache directory: %w

What it means

SyncObjects calls os.MkdirAll to create the local remote-cache directory (mode 0700) and wraps any filesystem failure. This is an environment/filesystem problem: the directory could not be created at the resolved path.

Source

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

// GetGCSClient returns a GCS client that uses Client libraries.
var GetGCSClient = func() gscClient {
	return &client.Native{}
}

type gscClient interface {
	// Downloads the content that match the given src uri and subfolders.
	DownloadRecursive(ctx context.Context, src, dst string) error
}

// SyncObjects syncs the target Google Cloud Storage objects with skaffold's local cache and returns the local path to the objects.
func SyncObjects(ctx context.Context, g latest.GoogleCloudStorageInfo, opts config.SkaffoldOptions) (string, error) {
	remoteCacheDir, err := config.GetRemoteCacheDir(opts)
	if err != nil {
		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.

View on GitHub (pinned to a1189de023)

Solutions

  1. Check permissions on the parent directory: `ls -ld $(dirname <remoteCacheDir>)` and fix with chmod/chown
  2. Ensure no regular file exists at the cache dir path; remove or rename it
  3. Pick a writable cache dir (e.g. under $HOME or /tmp) via the remote-cache-dir option
  4. Verify the filesystem is writable and has free space (`df -h`)

Example fix

// before
--remote-cache-dir=/var/cache/skaffold
// after
--remote-cache-dir=$HOME/.skaffold/gcs-cache
Defensive patterns

Strategy: validation

Validate before calling

dir, err := config.GetRemoteCacheDir(opts)
if err != nil {
	return fmt.Errorf("cannot resolve cache dir: %w", err)
}
if fi, err := os.Stat(filepath.Dir(dir)); err != nil || !fi.IsDir() {
	return fmt.Errorf("parent %s is not a writable directory", filepath.Dir(dir))
}
if fi, err := os.Stat(dir); err == nil && !fi.IsDir() {
	return fmt.Errorf("%s exists and is a file; remove it", dir)
}

Type guard

func isPathError(err error) (*os.PathError, bool) {
	var pe *os.PathError
	ok := errors.As(err, &pe)
	return pe, ok
}

Try / catch

if err := gcs.SyncObjects(ctx, gcsInfo, opts); err != nil {
	var pe *os.PathError
	if errors.As(err, &pe) {
		log.Errorf("fs error on %s: %v (check permissions/EROFS)", pe.Path, pe.Err)
	}
	return err
}

Prevention

When it happens

Trigger: os.MkdirAll(remoteCacheDir, 0700) fails because a parent path component is a file (ENOTDIR), permission denied (EACCES), read-only filesystem (EROFS), or disk/quota issues.

Common situations: Remote cache dir configured under a root-owned path while running as unprivileged user; pointing the cache dir at a path where a regular file already exists; running in a read-only container filesystem; full disk in CI.

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/a9d5ab936af3c736. Report an issue: GitHub.