MHSanaei/3x-ui · error
somethingWentWrong
Error message
somethingWentWrong
What it means
In NodeController.updatePanel, 'somethingWentWrong' is the localized user-facing message for two failures: the request body failing ShouldBindJSON (malformed JSON, wrong types), or req.Ids being empty. The actual technical error (JSON bind error or 'no nodes selected') is passed as the detail argument and shown alongside. So the underlying cause is a bad or empty request body, not a server fault.
Source
Thrown at internal/web/controller/node.go:334
}
if err := a.nodeService.UpdateHeartbeat(id, patch); err != nil {
jsonMsg(c, I18nWeb(c, "pages.nodes.toasts.test"), err)
return
}
jsonObj(c, patch.ToUI(probeErr == nil), nil)
}
func (a *NodeController) updatePanel(c *gin.Context) {
var req struct {
Ids []int `json:"ids"`
Dev bool `json:"dev"`
}
if err := c.ShouldBindJSON(&req); err != nil {
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
return
}
if len(req.Ids) == 0 {
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), fmt.Errorf("no nodes selected"))
return
}
results, err := a.nodeService.UpdatePanels(req.Ids, req.Dev)
jsonMsgObj(c, I18nWeb(c, "pages.nodes.toasts.updateStarted"), results, err)
}
func (a *NodeController) history(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
jsonMsg(c, I18nWeb(c, "get"), err)
return
}
metric := c.Param("metric")
if !slices.Contains(service.NodeMetricKeys, metric) {
jsonMsg(c, "invalid metric", fmt.Errorf("unknown metric"))
return
}
bucket, err := strconv.Atoi(c.Param("bucket"))View on GitHub (pinned to ad32144c42)
Solutions
- Send a proper JSON body with a non-empty numeric ids array: {"ids":[1,2],"dev":false} with Content-Type: application/json.
- Check the detail error string in the response — it distinguishes bind failure from 'no nodes selected'.
- If using the panel UI, update the frontend build so the modal always sends the selected row ids.
- Ensure the request includes the session cookie/CSRF token so middleware does not mangle the body.
Example fix
# before
curl -X POST /panel/api/nodes/update -d 'ids=1' # not JSON
# after
curl -X POST /panel/api/nodes/update -H 'Content-Type: application/json' \
-d '{"ids":[1,2],"dev":false}' Defensive patterns
Strategy: validation
Validate before calling
type updatePanelReq struct {
Ids []int `json:"ids"`
Dev bool `json:"dev"`
}
if len(req.Ids) == 0 { /* disable submit button client-side */ } Type guard
function isValidUpdatePanelBody(b: unknown): b is { ids: number[]; dev?: boolean } {
const o = b as Record<string, unknown>
return Array.isArray(o?.ids) && o.ids.length > 0 && o.ids.every((n) => Number.isInteger(n))
} Prevention
- Always send Content-Type: application/json with a non-empty numeric ids array.
- Disable the submit action until at least one node row is selected.
- Read the detail field of the response to distinguish bind vs no-selection failures.
When it happens
Trigger: POST /panel/api/nodes/update (panel update endpoint) with a body that is not JSON, has ids as a string instead of array of numbers, or {"ids":[]} / {"dev":true} with ids omitted.
Common situations: API client sending form-encoded instead of JSON; a stale frontend build sending an older payload shape; CSRF middleware intercepting and body consumed; automation script forgetting the ids field.
Related errors
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/975237f28a711a46.
Report an issue: GitHub.