{"record":{"id":"3e1eca013ac47456","repo":"libnyanpasu/clash-nyanpasu","slug":"mutation-degradation","errorCode":null,"errorMessage":"[mutation-degradation]","messagePattern":"\\[mutation-degradation\\]","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"frontend/nyanpasu/src/pages/__root.tsx","lineNumber":188,"sourceCode":"  return m.mutation_degraded_item({\n    phase: localizeDegradationPhase(degradation.phase),\n    detail: localizeDegradationCode(degradation.code),\n  })\n}\n\nfunction MutationDegradationNotifier() {\n  useEffect(\n    () =>\n      // setMutationDegradationHandler returns a disposer; useEffect cleanup\n      // passes it through so StrictMode remount / HMR leave no dangling handler.\n      setMutationDegradationHandler((degradations) => {\n        if (degradations.length === 0) {\n          return\n        }\n\n        // Backend `message` is diagnostic-only; primary copy is phase + code.\n        for (const degradation of degradations) {\n          console.warn('[mutation-degradation]', {\n            phase: degradation.phase,\n            code: degradation.code,\n            retryable: degradation.retryable,\n            message: degradation.message,\n          })\n        }\n\n        const items = degradations.map(formatDegradationItem).join('; ')\n        message(m.mutation_degraded_summary({ items }), {\n          title: m.mutation_degraded_title(),\n          kind: 'warning',\n        }).catch((error) => {\n          console.error('[mutation-degradation] failed to show warning', error)\n        })\n      }),\n    [],\n  )\n  return null","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/frontend/nyanpasu/src/pages/__root.tsx#L170-L206","documentation":"The MutationDegradationNotifier component in the root route observes mutation-degradation events emitted by the state/config layer — cases where a mutation was applied but some post-commit side effect failed and the system degraded gracefully. For each degradation it logs a console.warn with phase, code, retryable, and message; the backend's message field is diagnostic-only, the primary copy is phase + code. This is a diagnostic log, not a thrown error.","triggerScenarios":"A config/profile patch mutation committed but a post-commit side effect (e.g. core restart, runtime config regeneration, tray/UI notification) failed; the backend reports a degradation entry with a phase, a code, and a retryable flag, and the notifier logs it.","commonSituations":"Core process fails to restart after a config change; a side effect times out after a config patch; transient IPC errors while saving profile changes. Users see degraded behavior (stale runtime config) while persisted state is fine.","solutions":["Read the logged `phase` and `code` fields — they identify which post-commit side effect degraded and why.","If `retryable` is true, retry the mutation or trigger the affected action (e.g. restart core) — transient side-effect failures often succeed on retry.","If not retryable, fix the underlying condition indicated by the code (e.g. invalid runtime config, missing core binary) and re-apply the change.","Use the `message` field only as diagnostic detail; rely on phase + code for user-facing copy and triage."],"exampleFix":"// before: ignoring degradations silently\nawait client.patch_app_config(patch);\n// after: check result and handle degraded side effects\nconst result = await client.patch_app_config(patch);\nif (result.degradations.some(d => d.retryable)) {\n  await client.restart_core().catch(reportDegraded);\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await client.patch_app_config(patch);\n} catch (e) {\n  if (e.degradations?.some(d => d.retryable)) {\n    await client.restart_core(); // retry the degraded side effect\n  } else {\n    throw e;\n  }\n}","preventionTips":["After any config mutation, check for degradation entries and act on non-empty phase/code pairs.","Retry retryable degradations (e.g. restart core) instead of leaving stale runtime config.","Treat backend `message` as diagnostic-only; alert users with phase + code copy.","Monitor these warnings in logs to catch recurring side-effect failures (core binary missing, IPC timeouts)."],"tags":["diagnostics","degradation","side-effects","console-warning"],"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"}