{"record":{"id":"6b662d02d33ad7d2","repo":"decolua/9router","slug":"failed-to-toggle-dns","errorCode":null,"errorMessage":"Failed to toggle DNS","messagePattern":"Failed to toggle DNS","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/app/(dashboard)/dashboard/cli-tools/components/MitmToolCard.js","lineNumber":109,"sourceCode":"      doDnsAction(action, \"\");\n    } else {\n      setPendingDnsAction(action);\n      setShowPasswordModal(true);\n      setModalError(null);\n    }\n  };\n\n  const doDnsAction = async (action, password) => {\n    setLoading(true);\n    setWarning(null);\n    try {\n      const res = await fetch(\"/api/cli-tools/antigravity-mitm\", {\n        method: \"PATCH\",\n        headers: { \"Content-Type\": \"application/json\" },\n        body: JSON.stringify({ tool: tool.id, action, sudoPassword: password }),\n      });\n      const data = await res.json();\n      if (!res.ok) throw new Error(data.error || \"Failed to toggle DNS\");\n\n      if (action === \"enable\") {\n        setWarning(`Restart ${tool.name} to apply changes`);\n      }\n\n      setShowPasswordModal(false);\n      setSudoPassword(\"\");\n      onDnsChange?.(data);\n    } catch { /* ignore */ } finally {\n      setLoading(false);\n      setPendingDnsAction(null);\n    }\n  };\n\n  const handleConfirmPassword = () => {\n    if (!sudoPassword.trim()) {\n      setModalError(\"Sudo password is required\");\n      return;","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/app/(dashboard)/dashboard/cli-tools/components/MitmToolCard.js#L91-L127","documentation":"MitmToolCard's doDnsAction throws this when the PATCH to /api/cli-tools/antigravity-mitm fails and the response has no explicit error message. The endpoint toggles a system DNS override for the MITM tool, which typically requires elevation (sudo password); the fallback message hides whether it was auth, wrong sudo password, or an OS-level failure.","triggerScenarios":"PATCH /api/cli-tools/antigravity-mitm with {tool, action:'enable'|'disable', sudoPassword} returns non-2xx: wrong/empty sudo password, server cannot modify resolv.conf or the OS resolver, backend helper missing, or unauthenticated session.","commonSituations":"User submits the password modal with an incorrect sudo password; on systems where /etc/resolv.conf is managed by systemd-resolved or NetworkManager and cannot be written; action enable/disable sent with a tool id the backend doesn't recognize.","solutions":["Inspect the response body/status from the PATCH call for the server's real error text","Re-enter the sudo password carefully (wrong passwords commonly surface as this generic error)","Check whether the backend can modify the system resolver config (permissions, systemd-resolved conflicts) via server logs","Retry the toggle after fixing OS-level conflicts (e.g. disable systemd-resolved DNS stub handling)"],"exampleFix":"// before\nif (!res.ok) throw new Error(data.error || \"Failed to toggle DNS\");\n// after\nif (!res.ok) throw new Error(data.error || `Failed to toggle DNS (HTTP ${res.status})`);","handlingStrategy":"try-catch","validationCode":"// before toggling\nif (!password) { setShowPasswordModal(true); return; }","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(\"/api/cli-tools/antigravity-mitm\", { method: \"PATCH\", body: JSON.stringify({ tool, action, sudoPassword: password }) });\n  const data = await res.json().catch(() => ({}));\n  if (!res.ok) throw new Error(data.error || `Failed to toggle DNS (HTTP ${res.status})`);\n} catch (e) {\n  setWarning(e.message);\n}","preventionTips":["Confirm the sudo password before submitting; retry once on failure","Check that the OS resolver (systemd-resolved/NetworkManager) isn't locking the config","Surface res.status alongside data.error in the UI","Read server logs after failed toggles"],"tags":["http","dns","system-configuration","dashboard"],"backgroundTag":"http-request-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}