{"record":{"id":"cdd6722244a1d183","repo":"QuantumNous/new-api","slug":"delete-failed","errorCode":null,"errorMessage":"Delete failed","messagePattern":"Delete failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"web/src/features/system-info/components/system-instances-panel.tsx","lineNumber":530,"sourceCode":"  const instances = instancesQuery.data ?? []\n  const staleInstances = instances.filter(\n    (instance) => instance.status === 'stale'\n  )\n  const hasStaleInstances = staleInstances.length > 0\n  const loading = instancesQuery.isLoading\n  const refreshing = instancesQuery.isFetching && !instancesQuery.isLoading\n\n  const invalidateInstances = async () => {\n    await queryClient.invalidateQueries({\n      queryKey: ['system-info', 'instances'],\n    })\n  }\n\n  const deleteStaleInstanceMutation = useMutation({\n    mutationFn: async (nodeName: string) => {\n      const res = await deleteStaleSystemInstance(nodeName)\n      if (!res.success) {\n        throw new Error(res.message || t('Delete failed'))\n      }\n      return res\n    },\n    onMutate: (nodeName) => {\n      setDeletingNodeName(nodeName)\n    },\n    onSuccess: async () => {\n      toast.success(t('Deleted stale instance'))\n      await invalidateInstances()\n      setDeleteTarget(null)\n    },\n    onError: (error) => {\n      toast.error(error instanceof Error ? error.message : t('Delete failed'))\n      void invalidateInstances()\n    },\n    onSettled: () => {\n      setDeletingNodeName(null)\n    },","sourceCodeStart":512,"sourceCodeEnd":548,"githubUrl":"https://github.com/QuantumNous/new-api/blob/e2c7aa7b102c2075eae2377df3508658d45e88dc/web/src/features/system-info/components/system-instances-panel.tsx#L512-L548","documentation":"Thrown by deleteStaleInstanceMutation when deleteStaleSystemInstance(nodeName) rejects or returns success=false. The message is a fallback; the server's res.message wins when present. onError additionally re-invalidates the instances query so the table reflects true state.","triggerScenarios":"DELETE of a stale instance by nodeName where the node name does not exist (already cleaned by another admin or by node rejoin), the instance is no longer stale (heartbeats resumed between load and click), non-admin token, or backend error while removing the node's record.","commonSituations":"Two admins cleaning stale nodes concurrently; a flapping node that goes stale then rejoins; permission mismatch between the frontend page and the backend route guard; database error during delete.","solutions":["Read the server's message in the failed request's response body; it distinguishes 'not found' from permission or DB errors.","If the node rejoined, let the poll refresh; the row will stop being stale and no delete is needed.","Confirm the account has admin permission for instance management endpoints.","Retry after the automatic invalidation refreshes the list, deleting only rows still marked stale."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"onError: (error) => {\n  toast.error(error instanceof Error ? error.message : t('Delete failed'))\n  void invalidateInstances() // resync UI with true server state\n}","preventionTips":["Always invalidate the instances query in onError so stale rows cannot be re-acted upon.","Delete only rows still marked stale after a fresh refetch.","Propagate the server's message instead of the generic fallback so users see the real reason."],"tags":["system-info","instances","tanstack-query","api-error"],"backgroundTag":null,"analyzedSha":"e2c7aa7b102c2075eae2377df3508658d45e88dc","analyzedAt":"2026-08-15T10:35:18.111Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}