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

  1. Send a proper JSON body with a non-empty numeric ids array: {"ids":[1,2],"dev":false} with Content-Type: application/json.
  2. Check the detail error string in the response — it distinguishes bind failure from 'no nodes selected'.
  3. If using the panel UI, update the frontend build so the modal always sends the selected row ids.
  4. 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

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.