{"record":{"id":"abb126287ec60f0c","repo":"Crosstalk-Solutions/project-nomad","slug":"failed-to-fetch-update-logs","errorCode":null,"errorMessage":"Failed to fetch update logs","messagePattern":"Failed to fetch update logs","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"admin/inertia/pages/settings/update.tsx","lineNumber":141,"sourceCode":"    try {\n      setError(null)\n      seenAdvancedStageRef.current = false\n      setIsUpdating(true)\n      const response = await api.startSystemUpdate()\n      if (!response || !response.success) {\n        throw new Error('Failed to start update')\n      }\n    } catch (err: any) {\n      setIsUpdating(false)\n      setError(err.response?.data?.error || err.message || 'Failed to start update')\n    }\n  }\n\n  const handleViewLogs = async () => {\n    try {\n      const response = await api.getSystemUpdateLogs()\n      if (!response) {\n        throw new Error('Failed to fetch update logs')\n      }\n      setLogs(response.logs)\n      setShowLogs(true)\n    } catch (err) {\n      setError('Failed to fetch update logs')\n    }\n  }\n\n  const checkVersionMutation = useMutation({\n    mutationKey: ['checkLatestVersion'],\n    mutationFn: () => api.checkLatestVersion(true),\n    onSuccess: (data) => {\n      if (data) {\n        setVersionInfo({\n          updateAvailable: data.updateAvailable,\n          latestVersion: data.latestVersion,\n          currentVersion: data.currentVersion,\n        })","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/Crosstalk-Solutions/project-nomad/blob/0bd1c6f4f9888d577fe232de06ac144bb8337131/admin/inertia/pages/settings/update.tsx#L123-L159","documentation":"Thrown by handleViewLogs when api.getSystemUpdateLogs() resolves falsy (or the request rejects). The catch then discards the underlying cause and sets the generic string on the page.","triggerScenarios":"GET of update logs returning empty body (e.g. no logs exist yet so backend returns null), 401/403 from auth middleware, or the log file unreadable on the server side.","commonSituations":"Opening logs before any update has run (log file missing), permissions on the log directory, or a stale admin token after session timeout.","solutions":["Check the actual HTTP status of the logs request in devtools","Make the backend return {logs: []} instead of null/204 when no logs exist","Preserve the original error in the catch instead of overwriting with the generic message","Verify admin auth token is still valid when the modal is opened"],"exampleFix":"// before\nconst response = await api.getSystemUpdateLogs()\nif (!response) {\n  throw new Error('Failed to fetch update logs')\n}\n// after\nconst response = await api.getSystemUpdateLogs()\nconst logs = response?.logs ?? []\nsetLogs(logs)\nsetShowLogs(true)","handlingStrategy":"validation","validationCode":"const exists = await api.getSystemUpdateLogs().catch(() => null)\nif (exists?.logs) { setLogs(exists.logs) } else { setLogs([]) }","typeGuard":"const hasLogs = (r: unknown): r is { logs: string[] } =>\n  Array.isArray((r as any)?.logs)","tryCatchPattern":"try {\n  const r = await api.getSystemUpdateLogs()\n  setLogs(r?.logs ?? [])\n  setShowLogs(true)\n} catch (e) {\n  setError(e instanceof Error ? e.message : 'Failed to fetch update logs')\n}","preventionTips":["Backend should return {logs:[]} instead of null when no logs exist","Preserve the original error message in the catch block","Only offer View Logs after an update has actually run"],"tags":["system-update","logs","frontend"],"backgroundTag":"empty-api-response","analyzedSha":"0bd1c6f4f9888d577fe232de06ac144bb8337131","analyzedAt":"2026-08-27T05:34:15.424Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}