{"record":{"id":"23aede31c496e77e","repo":"flipped-aurora/gin-vue-admin","slug":"error-23aede","errorCode":null,"errorMessage":"日志日期格式不正确","messagePattern":"日志日期格式不正确","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/service/system/sys_log_viewer.go","lineNumber":30,"sourceCode":"\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\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}","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_log_viewer.go#L12-L48","documentation":"ErrInvalidLogDate is returned when a `date` parameter is not a strict \"YYYY-MM-DD\" calendar date. validateLogDate parses with time.Parse(\"2006-01-02\") and requires the re-formatted value to equal the input, so \"2025-8-1\", \"2025-02-30\", or \"20250801\" are rejected. It is used by ListFiles, ReadContent and openValidatedLogFile, also acting as the first path-safety filter on date directory names.","triggerScenarios":"Log-viewer list-files/content calls with date=\"2025-8-1\", \"2025-02-30\" (nonexistent day), \"08/30/2025\", \"2025-08-31 extra\", or any non-canonical string passed as the date segment.","commonSituations":"Client formatting dates without zero padding; timezone math producing invalid day values; users typing dates manually; API consumers guessing the expected format.","solutions":["Send date strictly as zero-padded \"YYYY-MM-DD\" (e.g. \"2025-08-30\").","Validate client-side with ^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$ and a real-calendar check.","Derive the date from month values returned by the list-dates API instead of constructing manually.","Trim and normalize input before sending."],"exampleFix":"// before\nGET /logViewer/files?date=2025-8-1   // ErrInvalidLogDate\n// after\nGET /logViewer/files?date=2025-08-01","handlingStrategy":"validation","validationCode":"var dateRe = regexp.MustCompile(`^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$`)\nif !dateRe.MatchString(date) {\n\treturn fmt.Errorf(\"date must be YYYY-MM-DD, got %q\", date)\n}","typeGuard":"func isValidLogDate(s string) bool {\n\tparsed, err := time.Parse(\"2006-01-02\", s)\n\treturn err == nil && parsed.Format(\"2006-01-02\") == s\n}","tryCatchPattern":"files, err := client.ListFiles(ctx, date)\nif err != nil && errors.Is(err, ErrInvalidLogDate) {\n\t// normalize the date to strict YYYY-MM-DD and retry once\n}","preventionTips":["Always zero-pad month and day components.","Use calendar-aware formatting so nonexistent days (2025-02-30) can't be produced.","Derive dates from the list-dates API rather than manual input.","Trim and normalize input before the request."],"tags":["go","validation","log-viewer"],"backgroundTag":"invalid-date-format","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}