Billionmail/BillionMail · warning
start time must be greater or equal to end time
Error message
start time must be greater or equal to end time
What it means
Overview validates the requested time window and defaults EndTime to now when zero. If EndTime is earlier than StartTime the handler rejects the request with this error, since the statistics query assumes a valid forward-looking range.
Source
Thrown at core/internal/controller/overview/overview_v1_overview.go:23
"billionmail-core/internal/service/public"
"context"
"fmt"
"time"
"github.com/gogf/gf/v2/util/gconv"
"billionmail-core/api/overview/v1"
)
func (c *ControllerV1) Overview(ctx context.Context, req *v1.OverviewReq) (res *v1.OverviewRes, err error) {
res = &v1.OverviewRes{}
if req.EndTime == 0 {
req.EndTime = time.Now().Unix()
}
if req.EndTime < req.StartTime {
err = fmt.Errorf("start time must be greater or equal to end time")
return
}
overview := maillog_stat.NewOverview()
overviewMap := overview.Overview(req.CampaignId, req.Domain, req.StartTime, req.EndTime)
err = gconv.Struct(overviewMap, &res.Data)
if err != nil {
err = fmt.Errorf("failed to convert overview data: %v", err)
return
}
res.SetSuccess(public.LangCtx(ctx, "Success"))
return
}
View on GitHub (pinned to fc36c76c05)
Solutions
- Ensure StartTime <= EndTime in Unix seconds
- Convert millisecond timestamps to seconds before sending
- Sync clocks (NTP) if timestamps come from the client machine
- Swap values if accidentally reversed
Example fix
// before
params: { start_time: Date.now(), end_time: Date.now() - 86400000 }
// after
const end = Math.floor(Date.now()/1000);
params: { start_time: end - 86400, end_time: end } Defensive patterns
Strategy: validation
Validate before calling
const end = endTime || Math.floor(Date.now()/1000);
if (startTime > end) throw new Error('start_time must be <= end_time (Unix seconds)'); Type guard
function isUnixSeconds(n: unknown): n is number {
return typeof n === 'number' && Number.isInteger(n) && n < 1e11;
} Try / catch
try {
const data = await api.overview({ start_time: s, end_time: e });
} catch (err) {
if (String(err.message).includes('greater or equal to end time')) {
[s, e] = [Math.min(s, e), Math.max(s, e)];
}
} Prevention
- Normalize all timestamps to Unix seconds before sending
- Omit end_time to use the server's now-default
- Enforce forward-only ranges in dashboard builders
When it happens
Trigger: Calling the overview API with StartTime > EndTime; passing StartTime in milliseconds while server expects seconds (so start looks like the far future); relying on the EndTime=0 default while sending a future StartTime.
Common situations: Reversed parameters in a dashboard query builder; unit mismatch (13-digit ms timestamps); clock skew on client machines; copying query params from a tool where the order was different.
Related errors
- start time must be greater or equal to end time
- required column 'email' not found
- You cannot create more than 5000 batches
- No log files found in the given date range
- invalid start_date: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/c74773e0861ea64c.
Report an issue: GitHub.