MHSanaei/3x-ui · error
invalid bucket
Error message
invalid bucket
What it means
parseHistoryBucket in ServerController is the shared guard for all /server/history endpoints (CPU, system metrics, Xray metrics, observatory). It Atoi-parses c.Param("bucket"), requires >0, and requires service.IsAllowedHistoryBucket to accept it; failure writes 'invalid bucket' / 'unsupported bucket' and signals the handler to return. Same semantics as the node-side guard but for server-wide history.
Source
Thrown at internal/web/controller/server.go:117
})
_, _ = c.AddFunc("@every 1m", func() {
if err := service.PersistSystemMetrics(); err != nil {
logger.Warning("persist system metrics failed:", err)
}
})
}
// status returns the current server status information.
func (a *ServerController) status(c *gin.Context) { jsonObj(c, a.serverService.LastStatus(), nil) }
func (a *ServerController) getFail2banStatus(c *gin.Context) {
jsonObj(c, a.serverService.GetFail2banStatus(), nil)
}
func parseHistoryBucket(c *gin.Context) (int, bool) {
bucket, err := strconv.Atoi(c.Param("bucket"))
if err != nil || bucket <= 0 || !service.IsAllowedHistoryBucket(bucket) {
jsonMsg(c, "invalid bucket", fmt.Errorf("unsupported bucket"))
return 0, false
}
return bucket, true
}
// getCpuHistoryBucket retrieves aggregated CPU usage history based on the specified time bucket.
// Kept for back-compat; new callers should use /history/cpu/:bucket which
// returns {"t","v"} (uniform across all metrics) instead of {"t","cpu"}.
func (a *ServerController) getCpuHistoryBucket(c *gin.Context) {
bucket, ok := parseHistoryBucket(c)
if !ok {
return
}
jsonObj(c, a.serverService.AggregateCpuHistory(bucket, 60), nil)
}
// getMetricHistoryBucket returns up to 60 buckets of history for a single
// system metric (cpu, mem, netUp, netDown, online, load1/5/15). TheView on GitHub (pinned to ad32144c42)
Solutions
- Call with an allowed integer bucket (verify against service.IsAllowedHistoryBucket for your build).
- Drop stale bookmarks/dashboard URLs after upgrading; refetch bucket options from the UI.
- Log the parsed bucket in your client when a 400 comes back to spot unit confusion (minutes vs seconds).
Example fix
# before GET /panel/api/server/history/cpu/1440 # guessed value, not allowed # after GET /panel/api/server/history/cpu/3600
Defensive patterns
Strategy: validation
Validate before calling
if !service.IsAllowedHistoryBucket(bucket) {
return fmt.Errorf("bucket %d not allowed; use one of %v", bucket, service.AllowedHistoryBuckets)
} Prevention
- Centralize bucket choices in one constant list shared by frontend and backend docs.
- Validate dashboard-configured bucket values against the current build after upgrades.
- Treat this 400 as permanent — do not retry with the same value.
When it happens
Trigger: GET /panel/api/server/history/cpu/:bucket (or the metric/xray-metric/observatory variants) with bucket=0, negative, non-integer, or an integer not in the allowed set.
Common situations: Bookmark or dashboard URL from an older version using a bucket size the new build dropped; typo in the path; scripts reusing a node-side bucket that differs from the server-side set.
Related errors
- invalid metric
- invalid bucket
- invalid metric
- invalid metric (unknown metric)
- invalid tag (unknown observatory tag)
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/ba8b26f3c20fadf0.
Report an issue: GitHub.