{"record":{"id":"975237f28a711a46","repo":"MHSanaei/3x-ui","slug":"somethingwentwrong","errorCode":null,"errorMessage":"somethingWentWrong","messagePattern":"somethingWentWrong","errorType":"http","errorClass":null,"httpStatus":200,"severity":"error","filePath":"internal/web/controller/node.go","lineNumber":334,"sourceCode":"\t}\n\tif err := a.nodeService.UpdateHeartbeat(id, patch); err != nil {\n\t\tjsonMsg(c, I18nWeb(c, \"pages.nodes.toasts.test\"), err)\n\t\treturn\n\t}\n\tjsonObj(c, patch.ToUI(probeErr == nil), nil)\n}\n\nfunc (a *NodeController) updatePanel(c *gin.Context) {\n\tvar req struct {\n\t\tIds []int `json:\"ids\"`\n\t\tDev bool  `json:\"dev\"`\n\t}\n\tif err := c.ShouldBindJSON(&req); err != nil {\n\t\tjsonMsg(c, I18nWeb(c, \"somethingWentWrong\"), err)\n\t\treturn\n\t}\n\tif len(req.Ids) == 0 {\n\t\tjsonMsg(c, I18nWeb(c, \"somethingWentWrong\"), fmt.Errorf(\"no nodes selected\"))\n\t\treturn\n\t}\n\tresults, err := a.nodeService.UpdatePanels(req.Ids, req.Dev)\n\tjsonMsgObj(c, I18nWeb(c, \"pages.nodes.toasts.updateStarted\"), results, err)\n}\n\nfunc (a *NodeController) history(c *gin.Context) {\n\tid, err := strconv.Atoi(c.Param(\"id\"))\n\tif err != nil {\n\t\tjsonMsg(c, I18nWeb(c, \"get\"), err)\n\t\treturn\n\t}\n\tmetric := c.Param(\"metric\")\n\tif !slices.Contains(service.NodeMetricKeys, metric) {\n\t\tjsonMsg(c, \"invalid metric\", fmt.Errorf(\"unknown metric\"))\n\t\treturn\n\t}\n\tbucket, err := strconv.Atoi(c.Param(\"bucket\"))","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/controller/node.go#L316-L352","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ncurl -X POST /panel/api/nodes/update -d 'ids=1'   # not JSON\n\n# after\ncurl -X POST /panel/api/nodes/update -H 'Content-Type: application/json' \\\n     -d '{\"ids\":[1,2],\"dev\":false}'","handlingStrategy":"validation","validationCode":"type updatePanelReq struct {\n    Ids []int `json:\"ids\"`\n    Dev bool  `json:\"dev\"`\n}\nif len(req.Ids) == 0 { /* disable submit button client-side */ }","typeGuard":"function isValidUpdatePanelBody(b: unknown): b is { ids: number[]; dev?: boolean } {\n  const o = b as Record<string, unknown>\n  return Array.isArray(o?.ids) && o.ids.length > 0 && o.ids.every((n) => Number.isInteger(n))\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["api","json","http-400","nodes"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}