{"record":{"id":"980c106251e52fb2","repo":"libnyanpasu/clash-nyanpasu","slug":"failed-to-update","errorCode":null,"errorMessage":"Failed to update","messagePattern":"Failed to update","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/nyanpasu/src/pages/(main)/main/settings/clash/_modules/core-manager-card.tsx","lineNumber":50,"sourceCode":"  SettingsCard,\n  SettingsCardContent,\n  SettingsCardFooter,\n} from '../../_modules/settings-card'\n\nfunction useCoreUpdateTask(\n  core?: ClashCore | null,\n  item?: ClashCoresDetail | null,\n) {\n  const { query, updateCore, inspectUpdater } = useClashCores()\n\n  const [updater, setUpdater] = useState<UpdaterSummary>()\n\n  const task = useBlockTask(`core-manager-update-${core}`, async () => {\n    try {\n      const updaterId = await updateCore.mutateAsync(core!)\n\n      if (!updaterId) {\n        throw new Error('Failed to update')\n      }\n\n      await new Promise<void>((resolve, reject) => {\n        const interval = setInterval(async () => {\n          const result = await inspectUpdater(updaterId)\n\n          if (!result) {\n            reject(new Error('Failed to inspect updater'))\n            clearInterval(interval)\n            return\n          }\n\n          setUpdater(result)\n\n          if (\n            isObject(result.downloader.state) &&\n            Object.prototype.hasOwnProperty.call(\n              result.downloader.state,","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/frontend/nyanpasu/src/pages/(main)/main/settings/clash/_modules/core-manager-card.tsx#L32-L68","documentation":"useBlockTask for core updates throws 'Failed to update' when updateCore.mutateAsync resolves to a falsy updaterId. A null/empty id means the backend did not register an updater task, so progress polling cannot proceed.","triggerScenarios":"Calling the core update task from core-manager-card when the updateCore mutation succeeds but returns no updater id (backend refused or short-circuited the update, e.g. already on latest version or download could not start).","commonSituations":"Updating mihomo/clash core when the download service is unavailable, the version is already current, or the backend updater returned no task handle.","solutions":["Check backend logs for why the updater returned no id","Verify network connectivity to the core release source","Confirm the core is not already at the latest version; retry the update"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const updaterId = await updateCore.mutateAsync(core)\nif (!updaterId) {\n  // handle 'no update task' before polling\n  showToast('No update task started')\n  return\n}","typeGuard":"const hasUpdaterId = (v: unknown): v is string => typeof v === 'string' && v.length > 0","tryCatchPattern":"try {\n  await updateCoreTask(core)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Failed to update') {\n    showToast('Core update could not start; check backend logs')\n  }\n}","preventionTips":["Check whether an update is actually needed before starting the task","Verify the updater backend service is healthy","Surface falsy updater ids immediately instead of polling"],"tags":["updater","core-update","ipc"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}