{"record":{"id":"a9c2871ab9141753","repo":"flipped-aurora/gin-vue-admin","slug":"function-os-readdir-failed-err","errorCode":null,"errorMessage":"function os.ReadDir() failed, err:","messagePattern":"function os\\.ReadDir\\(\\) failed, err:","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/utils/upload/local.go","lineNumber":164,"sourceCode":"\tfor _, key := range keys {\n\t\tif err := l.DeleteFile(ctx, key); err != nil {\n\t\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(err).Error(\"function Local.DeleteFile() failed\")\n\t\t\tfailed = append(failed, DeleteFailure{Key: key, Err: err})\n\t\t}\n\t}\n\treturn failed, nil\n}\n\n// ListFiles 按前缀列举本地文件，cursor 为上次返回的最后一条文件名（不透明游标）。\nfunc (*Local) ListFiles(ctx context.Context, prefix, cursor string, limit int) ([]FileInfo, string, bool, error) {\n\tif limit <= 0 {\n\t\tlimit = 100\n\t}\n\n\tentries, err := os.ReadDir(global.GVA_CONFIG.Local.StorePath)\n\tif err != nil {\n\t\tlogger.WithCtx(ctx).Mod(\"upload\").Err(err).Error(\"function os.ReadDir() failed\")\n\t\treturn nil, \"\", false, errors.New(\"function os.ReadDir() failed, err:\" + err.Error())\n\t}\n\n\t// 仅保留普通文件，按文件名过滤\n\tnames := make([]string, 0, len(entries))\n\tnameToEntry := make(map[string]os.DirEntry, len(entries))\n\tfor _, entry := range entries {\n\t\tif entry.IsDir() {\n\t\t\tcontinue\n\t\t}\n\t\tname := entry.Name()\n\t\tif prefix != \"\" && !strings.HasPrefix(name, prefix) {\n\t\t\tcontinue\n\t\t}\n\t\tnames = append(names, name)\n\t\tnameToEntry[name] = entry\n\t}\n\n\t// 按文件名排序，按 cursor 之后开始分页","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/utils/upload/local.go#L146-L182","documentation":"This error is returned by Local.ListFiles when os.ReadDir on the configured store path (global.GVA_CONFIG.Local.StorePath) fails. ReadDir fails when the directory does not exist, the process lacks read permission, or the path points to a file rather than a directory. The OS error is appended to the message.","triggerScenarios":"Calling ListFiles before any upload has ever created the store directory (MkdirAll only runs in UploadFile), pointing local.store-path at a nonexistent directory, or running with a user that cannot read the directory.","commonSituations":"Fresh deployments where nobody has uploaded yet; config typo in store-path; container volume not mounted so the path doesn't exist; permission changes after a security hardening pass.","solutions":["Create the store directory before listing: os.MkdirAll(global.GVA_CONFIG.Local.StorePath, os.ModePerm), or simply perform one upload first.","Verify local.store-path in config.yaml is correct and actually exists in the runtime environment.","Fix directory read permissions for the server process user (chmod/chown).","Check the appended OS error: 'no such file or directory' means create it; 'permission denied' means fix permissions."],"exampleFix":"// before\nfiles, _, _, err := local.ListFiles(ctx, \"\", \"\", 20) // store dir never created\n// after\n_ = os.MkdirAll(global.GVA_CONFIG.Local.StorePath, os.ModePerm)\nfiles, _, _, err := local.ListFiles(ctx, \"\", \"\", 20)","handlingStrategy":"validation","validationCode":"func ensureStoreDir(storePath string) error {\n    fi, err := os.Stat(storePath)\n    if os.IsNotExist(err) {\n        return os.MkdirAll(storePath, 0o755)\n    }\n    if err != nil {\n        return err\n    }\n    if !fi.IsDir() {\n        return fmt.Errorf(\"%s is not a directory\", storePath)\n    }\n    return nil\n}\n// call before ListFiles: ensureStoreDir(global.GVA_CONFIG.Local.StorePath)","typeGuard":null,"tryCatchPattern":"files, cursor, more, err := local.ListFiles(ctx, prefix, cursor, limit)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"function os.ReadDir() failed\") {\n        _ = os.MkdirAll(global.GVA_CONFIG.Local.StorePath, os.ModePerm)\n        files, cursor, more, err = local.ListFiles(ctx, prefix, cursor, limit)\n    }\n    if err != nil {\n        return err\n    }\n}","preventionTips":["Create the store directory during deployment/bootstrap, not on first upload.","Validate store-path exists and is a readable directory in a startup check.","Double-check config.yaml spelling of local.store-path per environment.","Ensure container volumes are mounted before the app starts serving requests."],"tags":["filesystem","permissions","go","pagination"],"backgroundTag":"directory-not-found","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}