{"record":{"id":"ea708037e47961ed","repo":"flipped-aurora/gin-vue-admin","slug":"error-ea7080","errorCode":null,"errorMessage":"日志目录不可读取","messagePattern":"日志目录不可读取","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_log_viewer.go","lineNumber":34,"sourceCode":"\n\t\"github.com/flipped-aurora/gin-vue-admin/server/global\"\n\tsystemReq \"github.com/flipped-aurora/gin-vue-admin/server/model/system/request\"\n\tsystemRes \"github.com/flipped-aurora/gin-vue-admin/server/model/system/response\"\n)\n\nconst (\n\tDefaultLogChunkLines = 500\n\tMaxLogChunkBytes     = 2 * 1024 * 1024\n\tlogReadBlockSize     = 64 * 1024\n)\n\nvar (\n\tErrInvalidLogMonth    = errors.New(\"日志月份格式不正确\")\n\tErrInvalidLogDate     = errors.New(\"日志日期格式不正确\")\n\tErrInvalidLogPath     = errors.New(\"日志文件路径不合法\")\n\tErrLogFileNotFound    = errors.New(\"日志文件不存在\")\n\tErrLogFileUnreadable  = errors.New(\"日志文件不可读取\")\n\tErrLogRootUnavailable = errors.New(\"日志目录不可读取\")\n)\n\ntype LogViewerService struct{}\n\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()","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_log_viewer.go#L16-L52","documentation":"ErrLogRootUnavailable is a sentinel error of the log viewer service meaning the configured log root directory itself cannot be opened, read, or stat'ed. It is returned by ListDates, ListFiles, configuredLogRoot, openConfiguredLogRoot, and countLogFiles, so virtually every log viewer listing operation fails when the root is inaccessible.","triggerScenarios":"Any log viewer API call (list months/dates/files or read a file) when the directory configured as the log root does not exist, is not a directory, or the process lacks read/execute permission on it; countLogFiles also surfaces it when the root cannot be read during counting.","commonSituations":"Misconfigured log path in config.yaml pointing to a missing directory; logs directory deleted by cleanup scripts; wrong volume mount in containers; permission changes after deployment or user switch; running in Docker where the log dir was never mounted.","solutions":["Verify the log directory path in your config (system log settings) actually exists on disk and create it if missing (mkdir -p).","Ensure the server process user has r+x on the directory (chmod/chown).","If in Docker/K8s, confirm the log volume is mounted at the configured path.","Re-run the operation after fixing; check server logs for the wrapped os error for the exact cause."],"exampleFix":"// config.yaml (before)\n// log-dir: /data/app/logs   # directory does not exist\n// after\n// sudo mkdir -p /data/app/logs\n// sudo chown appuser:appuser /data/app/logs","handlingStrategy":"validation","validationCode":"const cfg = require('./config.yaml').system.logDir\nif (!fs.existsSync(cfg) || !fs.statSync(cfg).isDirectory()) {\n  fs.mkdirSync(cfg, { recursive: true })\n}\nfs.accessSync(cfg, fs.constants.R_OK | fs.constants.X_OK)","typeGuard":null,"tryCatchPattern":"try {\n  const dates = await api.getLogDates(month)\n} catch (e) {\n  if (e.msg === '日志目录不可读取') {\n    notifyOps('log root missing/unreadable — check config path and mount')\n  } else throw e\n}","preventionTips":["Create the configured log directory at deployment time (init script / Dockerfile).","Mount the same path in containers that the config references.","Verify the path after config changes before restarting traffic."],"tags":["go","filesystem","log-viewer","configuration"],"backgroundTag":"log-directory-unavailable","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}