{"record":{"id":"48dfbafaeae33e5d","repo":"kubernetes/kops","slug":"error-creating-directories-for-destination-file-q-48dfba","errorCode":null,"errorMessage":"error creating directories for destination file %q: %v","messagePattern":"error creating directories for destination file %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/http.go","lineNumber":56,"sourceCode":"// If hash is non-nil, it will also verify that it matches the hash of the downloaded file.\nfunc DownloadURL(ctx context.Context, url string, dest string, hash *hashing.Hash) (*hashing.Hash, error) {\n\tif hash != nil {\n\t\tmatch, err := fileHasHash(dest, hash)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif match {\n\t\t\treturn hash, nil\n\t\t}\n\t}\n\n\treturn downloadURLToFile(ctx, url, dest, hash)\n}\n\nfunc downloadURLToFile(ctx context.Context, url string, destPath string, hash *hashing.Hash) (*hashing.Hash, error) {\n\tdir := filepath.Dir(destPath)\n\tif err := os.MkdirAll(dir, 0o755); err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating directories for destination file %q: %v\", destPath, err)\n\t}\n\n\toutput, err := os.CreateTemp(dir, \".\"+filepath.Base(destPath)+\".tmp\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error creating temporary file for download %q: %v\", destPath, err)\n\t}\n\ttempPath := output.Name()\n\tdefer os.Remove(tempPath)\n\n\tactual, err := downloadURLToWriter(ctx, url, output, hash)\n\tif closeErr := output.Close(); closeErr != nil && err == nil {\n\t\terr = closeErr\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif err := os.Chmod(tempPath, 0o644); err != nil {\n\t\treturn nil, fmt.Errorf(\"error setting mode on downloaded file %q: %v\", tempPath, err)","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/http.go#L38-L74","documentation":"downloadURLToFile prepares the destination directory with os.MkdirAll before downloading. If creating the parent directories fails, it wraps the OS error with the destination path. This is a filesystem permission/path problem, not a download problem.","triggerScenarios":"os.MkdirAll(filepath.Dir(destPath), 0o755) returns an error: unwritable parent, path component is a file, or read-only filesystem.","commonSituations":"Asset/ filestore destination under a root-owned directory; a file exists where a directory is expected; running without sufficient privileges; read-only container filesystem.","solutions":["Check the wrapped %v error and verify the parent directory is writable by the current user","Create the directory manually with correct ownership if needed","Remove or rename any non-directory file occupying the path","Run with elevated permissions or choose a writable destination"],"exampleFix":"// before\nmkdir -p /usr/local/share/kops (permission denied)\n// after\nsudo mkdir -p /usr/local/share/kops && sudo chown $(whoami) /usr/local/share/kops","handlingStrategy":"validation","validationCode":"dir := filepath.Dir(destPath)\nif info, err := os.Stat(dir); err == nil && !info.IsDir() {\n    return fmt.Errorf(\"%s exists and is not a directory\", dir)\n}\nif err := os.MkdirAll(dir, 0o755); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"if err := fi.DownloadURL(ctx, url, dest, nil); err != nil {\n    var pe *os.PathError\n    if errors.As(errors.Unwrap(err), &pe) || errors.As(err, &pe) {\n        log.Printf(\"filesystem error on %s: %v\", pe.Path, pe.Err)\n    }\n    return err\n}","preventionTips":["Pre-create asset directories with correct ownership before provisioning","Avoid destinations under read-only mounts","Run kops as a user with write access to the target path"],"tags":["filesystem","permissions","download"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}