{"record":{"id":"a6f3c736dd1fee21","repo":"jamiepine/voicebox","slug":"e-instanceof-error-e-message-errormessage","errorCode":null,"errorMessage":"e instanceof Error ? e.message : errorMessage","messagePattern":"e instanceof Error \\? e\\.message : errorMessage","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/components/ServerTab/GpuPage.tsx","lineNumber":286,"sourceCode":"          setTimeout(() => setRestartPhase('idle'), 2000);\n        }\n      } catch {\n        // Server still down, keep polling\n      }\n    }, 1000);\n  }, [queryClient, clearHealthPolling]);\n\n  const restartServerWithPolling = useCallback(\n    async (errorMessage: string) => {\n      setRestartPhase('stopping');\n      try {\n        await platform.lifecycle.restartServer();\n        setRestartPhase('waiting');\n        startHealthPolling();\n      } catch (e: unknown) {\n        clearHealthPolling();\n        setRestartPhase('idle');\n        throw new Error(e instanceof Error ? e.message : errorMessage);\n      }\n    },\n    [platform, startHealthPolling, clearHealthPolling],\n  );\n\n  const handleDownloadCuda = async () => {\n    setError(null);\n    try {\n      await apiClient.downloadCudaBackend();\n      setCudaStreaming(true);\n      refetchCudaStatus();\n    } catch (e: unknown) {\n      const msg = e instanceof Error ? e.message : t('settings.gpu.errors.downloadStart');\n      if (msg.includes('already downloaded')) {\n        refetchCudaStatus();\n      } else {\n        setError(msg);\n      }","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/jamiepine/voicebox/blob/51f49dea198384b4eb6087b72c17057c6eb1c1cd/app/src/components/ServerTab/GpuPage.tsx#L268-L304","documentation":"Not a standalone error message but an error-wrapping pattern in restartServerWithPolling(). It awaits platform.lifecycle.restartServer(), starts health polling, and in the catch block rethrows `new Error(e instanceof Error ? e.message : errorMessage)` — preferring the underlying Error's message, otherwise falling back to the caller-supplied errorMessage string. The downstream handler surfaces whichever message wins.","triggerScenarios":"platform.lifecycle.restartServer() rejects (subprocess failed to stop/start, IPC error, server binary missing). A non-Error value was thrown inside the platform layer (rare; loses the fallback message). The health-polling setup itself throws synchronously.","commonSituations":"CUDA/backend download corrupted the server binary so it won't start. Port already in use by a stale process. Permissions error spawning the server. Tauri/IPC bridge returned a string error instead of an Error object.","solutions":["Inspect the wrapped platform error's stack — the real cause is in platform.lifecycle.restartServer(), not this line.","Ensure no orphaned server process holds the port before restart (kill stale PID).","If a CUDA backend was just downloaded, verify the download completed and the binary is executable before restarting.","Preserve the original error via `{ cause: e }` instead of flattening to a message string for better debugging."],"exampleFix":"// before\nthrow new Error(e instanceof Error ? e.message : errorMessage);\n// after\nthrow new Error(e instanceof Error ? e.message : errorMessage, { cause: e });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isErrorWithMessage(e: unknown): e is Error {\n  return e instanceof Error;\n}","tryCatchPattern":"try {\n  await platform.lifecycle.restartServer();\n  setRestartPhase('waiting');\n  startHealthPolling();\n} catch (e: unknown) {\n  clearHealthPolling();\n  setRestartPhase('idle');\n  throw new Error(e instanceof Error ? e.message : errorMessage, { cause: e });\n}","preventionTips":["Preserve the original error via { cause: e } for debugging.","Free the port / kill stale PIDs before restart to avoid the common spawn failure.","Verify the server binary path exists, especially after a CUDA backend download."],"tags":["error-handling","platform","server-lifecycle","react","typescript","tauri"],"backgroundTag":null,"analyzedSha":"51f49dea198384b4eb6087b72c17057c6eb1c1cd","analyzedAt":"2026-08-12T16:51:42.824Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}