GoogleContainerTools/skaffold · error
failed to create file: %v
Error message
failed to create file: %v
What it means
DownloadObject wraps os.Create failures for the local destination file after the GCS reader was opened successfully. It means the local file could not be created — destination directory missing, no write permission, dst is a directory, or disk is full. The object content is never written in this case.
Source
Thrown at pkg/skaffold/gcs/client/native.go:332
}
if attrs.Name != "" {
matches = append(matches, attrs.Name)
}
}
return matches, nil
}
func (nb nativeBucketHandler) DownloadObject(ctx context.Context, localPath, uri string) error {
reader, err := nb.bucket.Object(uri).NewReader(ctx)
if err != nil {
return fmt.Errorf("failed to read object: %v", err)
}
defer reader.Close()
file, err := os.Create(localPath)
if err != nil {
return fmt.Errorf("failed to create file: %v", err)
}
defer file.Close()
if _, err := io.Copy(file, reader); err != nil {
return fmt.Errorf("failed to copy object to file: %v", err)
}
return nil
}
func (nb nativeBucketHandler) UploadObject(ctx context.Context, objName string, content *os.File) error {
wc := nb.bucket.Object(objName).NewWriter(ctx)
if _, err := io.Copy(wc, content); err != nil {
return fmt.Errorf("error copying file to GCS: %w", err)
}
if err := wc.Close(); err != nil {
return fmt.Errorf("error closing GCS writer: %w", err)
}View on GitHub (pinned to a1189de023)
Solutions
- Check the wrapped error for 'permission denied' / 'is a directory' / 'no space left' and fix accordingly
- Ensure the destination directory exists and is writable (MkdirAll with a verified writable dst)
- Free disk space or point dst to a larger volume
- Remove/rename any local directory that collides with the target file name
Example fix
// before
err := n.DownloadRecursive(ctx, "gs://bucket/data/**", "/mnt/ro-volume/out") // read-only
// after
dst := "/tmp/gcs-out" // writable location
if err := os.MkdirAll(dst, os.ModePerm); err != nil { /* handle */ }
if err := n.DownloadRecursive(ctx, "gs://bucket/data/**", dst); err != nil { /* handle */ } Defensive patterns
Strategy: validation
Validate before calling
func ensureDownloadTarget(dst string) error {
if fi, err := os.Stat(dst); err == nil {
if fi.IsDir() {
return fmt.Errorf("%s is a directory, expected file target", dst)
}
if fi.Mode().Perm()&0o200 == 0 {
return fmt.Errorf("%s is not writable", dst)
}
}
dir := filepath.Dir(dst)
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return fmt.Errorf("cannot create %s: %w", dir, err)
}
return nil
} Prevention
- Pre-create the destination directory tree and probe writability
- Check free disk space before large downloads
- Avoid destination paths that collide with existing directories
- Never download into read-only mounts
When it happens
Trigger: filepath.Join(dst, localPath) in DownloadRecursive points somewhere unwritable: parent dir not created (e.g. os.Stat falsely reported it exists), dst path is an existing directory with the object's name, or the filesystem is read-only/full.
Common situations: Downloading into a container volume mounted read-only; an object named like an existing local directory (e.g. object 'a' where ./a/ is a dir); ENOSPC on a small CI disk; running as non-root against root-owned paths.
Related errors
- failed to create directory: %v
- failed to read object: %v
- failed creating Google Cloud Storage cache directory for %q:
- writing %q to %q: %w
- reading .dockerignore: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/19dcba03cde8f54d.
Report an issue: GitHub.