{"record":{"id":"1a40c77196db0911","repo":"thedotmack/claude-mem","slug":"failed-to-fetch-logs-response-statustext","errorCode":null,"errorMessage":"Failed to fetch logs: ${response.statusText}","messagePattern":"Failed to fetch logs: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/ui/viewer/components/LogsModal.tsx","lineNumber":124,"sourceCode":"    const { scrollTop, scrollHeight, clientHeight } = contentRef.current;\n    return scrollHeight - scrollTop - clientHeight < 50;\n  }, []);\n\n  const scrollToBottom = useCallback(() => {\n    if (contentRef.current && wasAtBottomRef.current) {\n      contentRef.current.scrollTop = contentRef.current.scrollHeight;\n    }\n  }, []);\n\n  const fetchLogs = useCallback(async () => {\n    wasAtBottomRef.current = checkIfAtBottom();\n\n    setIsLoading(true);\n    setError(null);\n    try {\n      const response = await fetch('/api/logs');\n      if (!response.ok) {\n        throw new Error(`Failed to fetch logs: ${response.statusText}`);\n      }\n      const data = await response.json();\n      setLogs(data.logs || '');\n    } catch (err) {\n      setError(err instanceof Error ? err.message : 'Unknown error');\n    } finally {\n      setIsLoading(false);\n    }\n  }, [checkIfAtBottom]);\n\n  useEffect(() => {\n    scrollToBottom();\n  }, [logs, scrollToBottom]);\n\n  const handleClearLogs = useCallback(async () => {\n    if (!confirm('Are you sure you want to clear all logs?')) {\n      return;\n    }","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/ui/viewer/components/LogsModal.tsx#L106-L142","documentation":"LogsDrawer fetches log content from the viewer's internal /api/logs endpoint. If the HTTP response is not ok (non-2xx), it throws an Error embedding response.statusText, which is caught and shown in the drawer's error state. It signals the log-serving backend failed for this request.","triggerScenarios":"fetch('/api/logs') returns a non-ok status, e.g. viewer server not running / proxied incorrectly, endpoint returning 404/500, or a dev-server proxy misroute returning 404.","commonSituations":"Opening the Logs modal while the viewer's API server is down or restarted; reverse-proxy not forwarding /api/*; the logs endpoint erroring while reading the log file (permissions, missing file); stale UI bundle pointed at a server without the /api/logs route.","solutions":["Check the viewer backend is running and serving /api/logs (curl it directly and inspect status/body)","Inspect the network tab for the actual status code and response body; fix the server-side error reported there","Fix dev-server/proxy config so /api/logs is forwarded to the viewer API","Verify the log file the endpoint reads exists and is readable by the server process"],"exampleFix":"// before\nconst response = await fetch('/api/logs');\nif (!response.ok) {\n  throw new Error(`Failed to fetch logs: ${response.statusText}`);\n}\n// after\nconst response = await fetch('/api/logs');\nif (!response.ok) {\n  const body = await response.text();\n  throw new Error(`Failed to fetch logs: ${response.status} ${response.statusText} - ${body}`);\n}","handlingStrategy":"try-catch","validationCode":"const res = await fetch('/api/logs');\nif (!res.ok) throw new Error(`logs endpoint ${res.status}`);","typeGuard":"function isOk(r: Response): boolean { return r.ok; }","tryCatchPattern":"try {\n  const res = await fetch('/api/logs');\n  if (!res.ok) throw new Error(`Failed to fetch logs: ${res.status} ${res.statusText}`);\n  const data = await res.json();\n} catch (err) {\n  showError(err instanceof Error ? err.message : 'Unknown error');\n}","preventionTips":["Always check response.ok before parsing JSON","Include response.status and response body in error messages for debuggability","Health-check the viewer API before rendering the logs UI","Alert on server-side /api/logs failures"],"tags":["network","http","ui","fetch"],"backgroundTag":"http-error-response","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}