flipped-aurora/gin-vue-admin · error

ErrLogFileUnreadable

ErrLogFileUnreadable

Error message

%w: %v

What it means

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.

Solutions

  1. Ensure the service user can read the specific log file (check file mode, not just directory)
  2. Re-list files and retry — the file may have been rotated away
  3. Check errors.Is(err, ErrLogFileUnreadable) in the handler and surface a 'file unreadable' message
  4. Verify the file still exists at the path returned by ListFiles

Example fix

// before
content, err := svc.ReadContent(ctx, query) // EACCES on file
// after
chmod 640 /var/log/gva/2026-08/app.log
chown gva:gva /var/log/gva/2026-08/app.log
content, err := svc.ReadContent(ctx, query)
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const content = await readContent(query)
} catch (e) {
  if (/unreadable/i.test(e.message)) {
    showError('日志文件无法读取,可能已被轮转')
    await refreshFileList()
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/6cfe4fd3855d0871. Report an issue: GitHub.

Appendix: source

Thrown at server/service/system/sys_log_viewer.go:184

		return result, err
	}
	if query.Cursor != nil && *query.Cursor < 0 {
		return result, ErrInvalidLogPath
	}

	file, info, err := openValidatedLogFile(query.Date, query.Path)
	if err != nil {
		return result, err
	}
	defer file.Close()

	end := info.Size()
	if query.Cursor != nil && *query.Cursor <= end {
		end = *query.Cursor
	}
	start, limitedByBytes, err := findLogChunkStart(file, end)
	if err != nil {
		return result, fmt.Errorf("%w: %v", ErrLogFileUnreadable, err)
	}

	data, err := readLogRange(file, start, end)
	if err != nil {
		return result, fmt.Errorf("%w: %v", ErrLogFileUnreadable, err)
	}
	if int64(len(data)) < end-start {
		currentInfo, statErr := file.Stat()
		if statErr != nil || currentInfo.Size() < start {
			if statErr != nil {
				return result, fmt.Errorf("%w: %v", ErrLogFileUnreadable, statErr)
			}
			return result, ErrLogFileUnreadable
		}
		info = currentInfo
	}

	result.Content = string(data)

View on GitHub (pinned to 3136500ef3)