GoogleContainerTools/skaffold · error
failed to create directory: %v
Error message
failed to create directory: %v
What it means
DownloadRecursive wraps os.MkdirAll failures while recreating the GCS folder structure under the local destination. It means the local destination directories could not be created before downloading an object. The underlying cause (permissions, path conflicts, disk full) is included in the wrapped error.
Source
Thrown at pkg/skaffold/gcs/client/native.go:86
}
bucket, err := GetBucketManager(ctx, uriInfo.Bucket)
if err != nil {
return err
}
defer bucket.Close()
files, err := n.filesToDownload(ctx, bucket, uriInfo)
if err != nil {
return err
}
for uri, localPath := range files {
fullPath := filepath.Join(dst, localPath)
dir := filepath.Dir(fullPath)
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return fmt.Errorf("failed to create directory: %v", err)
}
}
if err := bucket.DownloadObject(ctx, fullPath, uri); err != nil {
return err
}
}
return nil
}
// Uploads a single file to the given dst.
func (n *Native) UploadFile(ctx context.Context, src, dst string) error {
f, err := os.Open(src)
if err != nil {
return fmt.Errorf("error opening file: %w", err)
}
defer f.Close()View on GitHub (pinned to a1189de023)
Solutions
- Ensure dst is a writable directory that does not collide with an existing file (check the wrapped %v for 'permission denied', 'not a directory', etc.)
- Pre-create the destination with os.MkdirAll(dst, os.ModePerm) and verify it succeeds before calling DownloadRecursive
- Run as a user with write access to dst, or chown/chmod the target directory
- Check disk space and filesystem errors (ENOSPC, EROFS) indicated in the wrapped error
Example fix
// before
cwd, _ := os.Getwd()
n.DownloadRecursive(ctx, "gs://bucket/dir/**", "./cache") // ./cache is a regular file
// after
if err := os.RemoveAll("./cache"); err != nil { /* handle */ }
if err := os.MkdirAll("./cache", os.ModePerm); err != nil { /* handle */ }
if err := n.DownloadRecursive(ctx, "gs://bucket/dir/**", "./cache"); err != nil { /* handle */ } Defensive patterns
Strategy: validation
Validate before calling
func ensureWritableDir(dst string) error {
if fi, err := os.Stat(dst); err == nil && !fi.IsDir() {
return fmt.Errorf("%s exists and is not a directory", dst)
}
if err := os.MkdirAll(dst, os.ModePerm); err != nil {
return fmt.Errorf("cannot create %s: %w", dst, err)
}
probe := filepath.Join(dst, ".write-probe")
if err := os.WriteFile(probe, nil, 0o644); err != nil {
return fmt.Errorf("%s is not writable: %w", dst, err)
}
return os.Remove(probe)
}
// call ensureWritableDir(dst) before DownloadRecursive Prevention
- Always pre-create and probe-writable the dst directory before recursive downloads
- Never point dst at a path occupied by a regular file
- Run downloads as a user with ownership of the destination volume
- Watch for ENOSPC; check free space before large recursive downloads
When it happens
Trigger: Calling Native.DownloadRecursive(ctx, src, dst) when filepath.Dir of a destination path exists in the object names but cannot be created: dst (or a path segment) points to a file, the process lacks write permission, or the path is invalid/too long.
Common situations: Running skaffold with a remote dependency under a read-only home directory; dst collides with an existing regular file (e.g. dst=./cache and ./cache is a file); running in a container as a non-root user against a root-owned volume; SELinux/AppArmor blocking mkdir.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- failed to create file: %v
- failed creating Google Cloud Storage cache directory for %q:
- writing %q to %q: %w
- reading .dockerignore: %w
- walking workspace: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/07adeee16aa4bc76.
Report an issue: GitHub.