{"record":{"id":"0eb6966e5a46cb56","repo":"flipped-aurora/gin-vue-admin","slug":"function-os-mkdirall-failed-err","errorCode":null,"errorMessage":"function os.MkdirAll() failed, err:","messagePattern":"function os\\.MkdirAll\\(\\) failed, err:","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/upload/local.go","lineNumber":45,"sourceCode":"//@object: *Local\n//@function: UploadFile\n//@description: 上传文件\n//@param: file *multipart.FileHeader\n//@return: string, string, error\n\nfunc (*Local) UploadFile(ctx context.Context, file *multipart.FileHeader) (string, string, error) {\n\t// 读取文件后缀\n\text := filepath.Ext(file.Filename)\n\t// 读取文件名并加密\n\tname := strings.TrimSuffix(file.Filename, ext)\n\tname = utils.MD5V([]byte(name))\n\t// 拼接新文件名\n\tfilename := name + \"_\" + time.Now().Format(\"20060102150405\") + ext\n\t// 尝试创建此路径\n\tmkdirErr := os.MkdirAll(global.GVA_CONFIG.Local.StorePath, os.ModePerm)\n\tif mkdirErr != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(mkdirErr).Error(\"function os.MkdirAll() failed\")\n\t\treturn \"\", \"\", errors.New(\"function os.MkdirAll() failed, err:\" + mkdirErr.Error())\n\t}\n\t// 拼接路径和文件名\n\tp := global.GVA_CONFIG.Local.StorePath + \"/\" + filename\n\tfilepath := global.GVA_CONFIG.Local.Path + \"/\" + filename\n\n\tf, openError := file.Open() // 读取文件\n\tif openError != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(openError).Error(\"function file.Open() failed\")\n\t\treturn \"\", \"\", errors.New(\"function file.Open() failed, err:\" + openError.Error())\n\t}\n\tdefer f.Close() // 创建文件 defer 关闭\n\n\tout, createErr := os.Create(p)\n\tif createErr != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(createErr).Error(\"function os.Create() failed\")\n\n\t\treturn \"\", \"\", errors.New(\"function os.Create() failed, err:\" + createErr.Error())\n\t}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/upload/local.go#L27-L63","documentation":"local.UploadFile creates the configured store directory with os.MkdirAll before writing the uploaded file. If the OS refuses (permission denied, path is a file, read-only filesystem), the mkdirErr is wrapped in this message and the upload aborts. This is purely a filesystem/permissions problem, not a network one.","triggerScenarios":"UploadFile(ctx, file, ...) when global.GVA_CONFIG.Local.StorePath cannot be created: parent directory lacks write permission, a regular file exists at that path, the disk is read-only or full, or the path is invalid for the OS.","commonSituations":"Docker volume mounted read-only, StorePath configured under /root without privileges, SELinux/AppArmor denials, systemd service with restrictive ProtectSystem/ReadOnlyPaths, config pointing at a path where a file (e.g. a bind-mounted file) already exists.","solutions":["Check the wrapped err text: 'permission denied' -> chown/chmod the StorePath parent for the server's user","Confirm the path in config Local.StorePath is correct and not colliding with an existing file","If running in Docker/K8s, ensure the volume is mounted read-write","On systemd, review hardening options (ProtectSystem, ReadOnlyPaths) or add ReadWritePaths for the store path","Check disk space and mount status (df -h, mount) for read-only remounts after errors"],"exampleFix":"// before\nstore-path: /var/lib/gva/uploads   # owned by root, server runs as gva\n// after\n# sudo mkdir -p /var/lib/gva/uploads && sudo chown gva:gva /var/lib/gva/uploads","handlingStrategy":"validation","validationCode":"storePath := global.GVA_CONFIG.Local.StorePath\nif fi, err := os.Stat(storePath); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"%s exists and is not a directory\", storePath)\n}\nif err := os.MkdirAll(storePath, os.ModePerm); err != nil {\n    return fmt.Errorf(\"store path not writable: %w\", err)\n}","typeGuard":"null","tryCatchPattern":"url, name, err := uploader.UploadFile(ctx, fileHeader, fileName)\nif err != nil {\n    if strings.Contains(err.Error(), \"os.MkdirAll() failed\") {\n        logger.Error(\"store path unusable — check permissions/mount\", zap.Error(err))\n        return c.JSON(500, gin.H{\"msg\": \"storage path unavailable\"})\n    }\n    return err\n}","preventionTips":["Create and chown the store path in deployment scripts/Dockerfile before start","Run the server as a user with write access to the store path","Check systemd hardening (ReadOnlyPaths/ProtectSystem) and Docker volume rw flags","Add a startup preflight that MkdirAll's the store path and fails fast on error","Monitor disk space and read-only remounts on the storage volume"],"tags":["filesystem","permissions","upload","local-storage"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}