Billionmail/BillionMail · error
end_time must greater than start_time
Error message
end_time must greater than start_time
What it means
filterAndPrepareTimeSection panics (via public.Lang localized message) when the requested query range is inverted: startTime is greater than endTime. The overview/statistics API cannot compute metrics over a negative time window, so it aborts the request instead of returning empty data.
Source
Thrown at core/internal/service/maillog_stat/overview.go:34
"github.com/gogf/gf/v2/util/gconv"
)
// Overview maillog data overview structure
type Overview struct{}
// NewOverview new overview instance
func NewOverview() *Overview {
return &Overview{}
}
// filterAndPrepareTimeSection filter and provide time section
func (o *Overview) filterAndPrepareTimeSection(startTime, endTime int64) (int64, int64) {
if startTime > 0 && endTime < 0 {
endTime = time.Now().Unix()
}
if startTime > endTime {
panic(public.Lang("end_time must greater than start_time"))
}
// Maximum time range is 1 year
if endTime-startTime > 31622400 {
startTime = endTime - 31622400 // 1 year
}
return startTime, endTime
}
// buildBaseQuery build basic query
func (o *Overview) buildBaseQuery(campaignID int64, domain string, startTime, endTime int64) *gdb.Model {
subQuery := "SELECT * FROM mailstat_send_mails WHERE true"
if startTime > 0 {
subQuery += fmt.Sprintf(" AND log_time_millis > %d", startTime*1000)
}
View on GitHub (pinned to fc36c76c05)
Solutions
- Validate in the caller/controller that startTime < endTime before invoking overview APIs and return a 400 instead
- Fix the frontend date-range component so it never emits start > end
- Convert timestamps consistently to Unix seconds (divide ms timestamps by 1000)
- Optionally harden filterAndPrepareTimeSection to swap/return an error instead of panicking
Example fix
// before
startTime, _ := strconv.ParseInt(ctx.Request.Get("start_time"), 10, 64)
endTime, _ := strconv.ParseInt(ctx.Request.Get("end_time"), 10, 64)
o.filterAndPrepareTimeSection(startTime, endTime)
// after
if startTime > endTime {
return gerror.New("start_time must be less than end_time")
}
o.filterAndPrepareTimeSection(startTime, endTime) Defensive patterns
Strategy: validation
Validate before calling
start, _ := strconv.ParseInt(startTimeStr, 10, 64)
end, _ := strconv.ParseInt(endTimeStr, 10, 64)
if start <= 0 { start = time.Now().AddDate(0, -1, 0).Unix() }
if end <= 0 { end = time.Now().Unix() }
if start > end { return errors.New("start_time must be <= end_time") } Try / catch
defer func() {
if r := recover(); r != nil {
if strings.Contains(fmt.Sprint(r), "end_time must greater than start_time") {
respondBadRequest("invalid time range")
} else { panic(r) }
}
}() Prevention
- Validate timestamp ordering in the controller before service calls
- Normalize ms-vs-s timestamps at the API boundary
- Fix date-range pickers so they cannot emit start > end
- Prefer returning a 400 error over panicking on bad input
When it happens
Trigger: Calling Overview, chartSendMail, chartBounceRate, chartOpenRate, sendMailDashboard or overviewProviders with query params where start > end — e.g. start=1700000000&end=1600000000, or a UI sending swapped date-picker values. Note: negative endTime is silently corrected to now, so only genuinely swapped positive ranges trigger the panic.
Common situations: Frontend date-range picker emitting reversed values; API clients constructing timestamps in ms instead of s (milliseconds look huge and can invert ranges); timezone handling shifting one boundary past the other; hardcoded default ranges where start defaults exceed a passed end.
Related errors
- end_time must greater than start_time
- Invalid operator:
- required column 'email' not found
- You cannot create more than 5000 batches
- No log files found in the given date range
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/2b262c693a41d4b9.
Report an issue: GitHub.