{"record":{"id":"127cc8df7ca43f29","repo":"GoogleContainerTools/skaffold","slug":"failed-creating-google-cloud-storage-cache-directo","errorCode":null,"errorMessage":"failed creating Google Cloud Storage cache directory for %q: %w","messagePattern":"failed creating Google Cloud Storage cache directory for %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/gcs/gsutil.go","lineNumber":100,"sourceCode":"\t\treturn \"\", fmt.Errorf(\"failed determining remote cache directory: %w\", err)\n\t}\n\tif err := os.MkdirAll(remoteCacheDir, 0700); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed creating remote cache directory: %w\", err)\n\t}\n\n\tsourceDir, err := getPerSourceDir(g)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed determining Google Cloud Storage remote cache directory for %q: %w\", g.Source, err)\n\t}\n\tcacheDir := filepath.Join(remoteCacheDir, sourceDir)\n\tif _, err := os.Stat(cacheDir); os.IsNotExist(err) {\n\t\t// If cache doesn't exist and cloning is disabled then we can't move forward.\n\t\tif opts.SyncRemoteCache.CloneDisabled() {\n\t\t\treturn \"\", syncDisabledErr(g, cacheDir)\n\t\t}\n\t\t// The subdirectory needs to exist to work with gsutil.\n\t\tif err := os.MkdirAll(cacheDir, 0700); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed creating Google Cloud Storage cache directory for %q: %w\", g.Source, err)\n\t\t}\n\t} else {\n\t\t// If sync property is false then skip fetching latest object from remote storage.\n\t\tif g.Sync != nil && !*g.Sync {\n\t\t\treturn cacheDir, nil\n\t\t}\n\t\t// If sync is turned off via flag `--sync-remote-cache` then skip fetching latest object from remote storage.\n\t\tif opts.SyncRemoteCache.FetchDisabled() {\n\t\t\treturn cacheDir, nil\n\t\t}\n\t}\n\n\tgcs := GetGCSClient()\n\tif err := gcs.DownloadRecursive(ctx, g.Source, cacheDir); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to cache Google Cloud Storage objects from %q: %w\", g.Source, err)\n\t}\n\treturn cacheDir, nil\n}","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/gcs/gsutil.go#L82-L118","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check permissions on the remote cache directory (default under ~/.config/skaffold) and the failing subdirectory; chown/chmod so the current user can write (0700).","If a regular file occupies the cacheDir path, delete it so the directory can be recreated.","Set a writable custom cache location via --remote-cache-dir, or free disk space if the disk is full.","Clear the entire remote cache directory and re-run so skaffold recreates it from scratch."],"exampleFix":"# before\n$ ls -l ~/.config/skaffold/cache/remote\n-rw-r--r-- 1 root root cache-dir   # stale file blocks mkdir\n# after\n$ sudo rm -rf ~/.config/skaffold/cache/remote/cache-dir\n$ sudo chown -R $USER ~/.config/skaffold/cache/remote","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(cacheDir); err == nil {\n    if info, ok := err.(nil); !ok { /* stat succeeded */ }\n}\n// pre-check writability of the parent cache dir before calling SyncObjects\nif fi, err := os.Stat(parentDir); err != nil || !fi.IsDir() || fi.Mode().Perm()&0200 == 0 {\n    return fmt.Errorf(\"cache dir %s not writable: %v\", parentDir, err)\n}","typeGuard":"func isPathError(err error) (*os.PathError, bool) {\n    var pe *os.PathError\n    if errors.As(err, &pe) {\n        return pe, true\n    }\n    return nil, false\n}","tryCatchPattern":"cacheDir, err := gcs.SyncObjects(ctx, gcsInfo, opts)\nif err != nil {\n    var pe *os.PathError\n    if errors.As(err, &pe) && os.IsPermission(pe.Err) {\n        log.Warnf(\"fix permissions on %s: %v\", pe.Path, pe.Err)\n        return retryWithNewCacheDir(ctx, \"--remote-cache-dir\", \"/tmp/skaffold-cache\")\n    }\n    return err\n}","preventionTips":["Run skaffold as a user that owns the remote cache directory; avoid mixing root and user runs.","Add a startup check that the --remote-cache-dir (or its default) exists, is a directory, and is writable.","Never store non-directory files inside the cache path tree.","Monitor disk space in CI; provision the cache on a writable volume."],"tags":["gcs","filesystem","cache","permissions"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}