{"record":{"id":"60011416e38ac798","repo":"flipped-aurora/gin-vue-admin","slug":"errlogrootunavailable","errorCode":"ErrLogRootUnavailable","errorMessage":"%w: %v","messagePattern":"%w: %v","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_log_viewer.go","lineNumber":56,"sourceCode":"\nfunc (s *LogViewerService) ListDates(ctx context.Context, month string) (result systemRes.LogDateList, err error) {\n\tresult = systemRes.LogDateList{Month: month, Dates: make([]systemRes.LogDateItem, 0)}\n\tif err = validateLogMonth(month); err != nil {\n\t\treturn result, err\n\t}\n\n\tlogRoot, exists, err := openConfiguredLogRoot()\n\tif err != nil {\n\t\treturn result, err\n\t}\n\tif !exists {\n\t\treturn result, nil\n\t}\n\tdefer logRoot.Close()\n\n\tentries, err := fs.ReadDir(logRoot.FS(), \".\")\n\tif err != nil {\n\t\treturn result, fmt.Errorf(\"%w: %v\", ErrLogRootUnavailable, err)\n\t}\n\tfor _, entry := range entries {\n\t\tif err = ctx.Err(); err != nil {\n\t\t\treturn result, err\n\t\t}\n\t\tif entry.Type()&os.ModeSymlink != 0 || !entry.IsDir() || !strings.HasPrefix(entry.Name(), month+\"-\") {\n\t\t\tcontinue\n\t\t}\n\t\tif validateLogDate(entry.Name()) != nil {\n\t\t\tcontinue\n\t\t}\n\t\tcount, countErr := countLogFiles(ctx, logRoot, entry.Name())\n\t\tif countErr != nil {\n\t\t\treturn result, countErr\n\t\t}\n\t\tif count == 0 {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_log_viewer.go#L38-L74","documentation":"ListDates reads the log root directory via an os.Root-scoped ReadDir. If reading the root itself fails (permission denied, root path removed, not a directory), the error is wrapped with ErrLogRootUnavailable using %w so callers can match with errors.Is.","triggerScenarios":"Calling ListDates when the configured log directory does not exist or the process lacks read permission on it; the directory was deleted/rotated while the service runs; logRoot opened but ReadDir on '.' fails.","commonSituations":"Wrong GVA_CONFIG log dir path in the environment; container where the log volume is not mounted; permissions changed after log rotation scripts ran.","solutions":["Verify the configured log root path exists and is a directory","Fix filesystem permissions so the service user can read the directory","Mount the log volume correctly in containerized deployments","Handle the error in the API layer with errors.Is(err, ErrLogRootUnavailable) and return a clear 500/404"],"exampleFix":"// before\nservice.ListDates(ctx, month) // fails: root missing\n// after\nif _, err := os.Stat(logDir); err != nil {\n  os.MkdirAll(logDir, 0o755)\n}\nresult, err := service.ListDates(ctx, month)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const dates = await listDates(month)\n} catch (e) {\n  if (e.code === 'ErrLogRootUnavailable' || /root/i.test(e.message)) {\n    showError('日志目录不可访问，请检查配置与权限')\n  }\n}","preventionTips":["Verify log dir config before deploying","Alert on log-root errors in monitoring"],"tags":["go","filesystem","logging","os-root"],"backgroundTag":"log-root-unavailable","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}