{"record":{"id":"6cfe4fd3855d0871","repo":"flipped-aurora/gin-vue-admin","slug":"errlogfileunreadable","errorCode":"ErrLogFileUnreadable","errorMessage":"%w: %v","messagePattern":"%w: %v","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_log_viewer.go","lineNumber":184,"sourceCode":"\t\treturn result, err\n\t}\n\tif query.Cursor != nil && *query.Cursor < 0 {\n\t\treturn result, ErrInvalidLogPath\n\t}\n\n\tfile, info, err := openValidatedLogFile(query.Date, query.Path)\n\tif err != nil {\n\t\treturn result, err\n\t}\n\tdefer file.Close()\n\n\tend := info.Size()\n\tif query.Cursor != nil && *query.Cursor <= end {\n\t\tend = *query.Cursor\n\t}\n\tstart, limitedByBytes, err := findLogChunkStart(file, end)\n\tif err != nil {\n\t\treturn result, fmt.Errorf(\"%w: %v\", ErrLogFileUnreadable, err)\n\t}\n\n\tdata, err := readLogRange(file, start, end)\n\tif err != nil {\n\t\treturn result, fmt.Errorf(\"%w: %v\", ErrLogFileUnreadable, err)\n\t}\n\tif int64(len(data)) < end-start {\n\t\tcurrentInfo, statErr := file.Stat()\n\t\tif statErr != nil || currentInfo.Size() < start {\n\t\t\tif statErr != nil {\n\t\t\t\treturn result, fmt.Errorf(\"%w: %v\", ErrLogFileUnreadable, statErr)\n\t\t\t}\n\t\t\treturn result, ErrLogFileUnreadable\n\t\t}\n\t\tinfo = currentInfo\n\t}\n\n\tresult.Content = string(data)","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_log_viewer.go#L166-L202","documentation":"ReadContent locates the byte range for the requested chunk via findLogChunkStart and reads it with readLogRange; any failure there (seek/read errors, file unreadable) is wrapped with ErrLogFileUnreadable so the API can report the log file content cannot be served.","triggerScenarios":"Calling ReadContent on a log file that cannot be seeked or read — permission denied on the file, file truncated/deleted mid-read, or an underlying I/O error during chunk scanning.","commonSituations":"Log file rotated (renamed/deleted) between listing and reading; file permissions stricter than directory permissions; log file on flaky storage; reading files owned by another user.","solutions":["Ensure the service user can read the specific log file (check file mode, not just directory)","Re-list files and retry — the file may have been rotated away","Check errors.Is(err, ErrLogFileUnreadable) in the handler and surface a 'file unreadable' message","Verify the file still exists at the path returned by ListFiles"],"exampleFix":"// before\ncontent, err := svc.ReadContent(ctx, query) // EACCES on file\n// after\nchmod 640 /var/log/gva/2026-08/app.log\nchown gva:gva /var/log/gva/2026-08/app.log\ncontent, err := svc.ReadContent(ctx, query)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const content = await readContent(query)\n} catch (e) {\n  if (/unreadable/i.test(e.message)) {\n    showError('日志文件无法读取，可能已被轮转')\n    await refreshFileList()\n  }\n}","preventionTips":["Re-list files before reading after rotation events","Keep file perms readable by the service user"],"tags":["go","filesystem","logging","file-read"],"backgroundTag":"log-file-unreadable","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}