{"record":{"id":"8538a8b9afd027fe","repo":"thedotmack/claude-mem","slug":"service-initializing-8538a8","errorCode":null,"errorMessage":"Service initializing","messagePattern":"Service initializing","errorType":"http","errorClass":null,"httpStatus":503,"severity":"warning","filePath":"src/services/worker/http/routes/ViewerRoutes.ts","lineNumber":81,"sourceCode":"    });\n  });\n\n  private handleViewerUI = this.wrapHandler((req: Request, res: Response): void => {\n    if (!viewerHtmlBytes) {\n      throw new Error('Viewer UI not found at any expected location');\n    }\n    res.setHeader('Content-Type', 'text/html; charset=utf-8');\n    res.send(viewerHtmlBytes);\n  });\n\n  private handleSSEStream = this.wrapHandler((req: Request, res: Response): void => {\n    try {\n      this.dbManager.getSessionStore();\n    } catch (initError: unknown) {\n      if (initError instanceof Error) {\n        logger.warn('HTTP', 'SSE stream requested before DB initialization', {}, initError);\n      }\n      res.status(503).json({ error: 'Service initializing' });\n      return;\n    }\n\n    res.setHeader('Content-Type', 'text/event-stream');\n    res.setHeader('Cache-Control', 'no-cache');\n    res.setHeader('Connection', 'keep-alive');\n\n    this.sseBroadcaster.addClient(res);\n\n    const projectCatalog = this.dbManager.getSessionStore().getProjectCatalog();\n    this.sseBroadcaster.broadcast({\n      type: 'initial_load',\n      projects: projectCatalog.projects,\n      sources: projectCatalog.sources,\n      projectsBySource: projectCatalog.projectsBySource,\n      timestamp: Date.now()\n    });\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/services/worker/http/routes/ViewerRoutes.ts#L63-L99","documentation":"HTTP 503 from the viewer's SSE endpoint. It probes dbManager.getSessionStore() as an initialization canary: during worker startup that call throws, the handler logs 'SSE stream requested before DB initialization' at WARN and refuses to open the event stream. Unlike the global /api gate (error 240), this guard is local to the viewer stream connection.","triggerScenarios":"A browser or EventSource client opens /sse (or the viewer page auto-connects) in the window between HTTP listen and DB initialization completing; aggressive reconnect logic hammering the endpoint during a slow boot.","commonSituations":"Viewer page opened immediately after worker start; EventSource auto-reconnect with zero backoff creating 503 bursts; dashboards that load on machine boot before the worker service finishes initializing.","solutions":["Let EventSource reconnect (it will succeed once init completes); configure reconnect with a small backoff","Gate the viewer page on /api/health returning ok before mounting the SSE client","If 503 persists, check worker logs for a session-store initialization failure (locked or missing SQLite database)"],"exampleFix":"// before\nconst es = new EventSource(`${base}/sse`); // 503 during boot, no retry logic\n\n// after\nasync function connectWhenReady() {\n  while (!(await fetch(`${base}/api/health`).then(r => r.ok).catch(() => false)))\n    await new Promise(r => setTimeout(r, 500));\n  return new EventSource(`${base}/sse`);\n}","handlingStrategy":"retry","validationCode":"while (!(await fetch(`${base}/api/health`).then(r => r.ok).catch(() => false)))\n  await new Promise(r => setTimeout(r, 500));\nconst es = new EventSource(`${base}/sse`); // connect only after readiness","typeGuard":"function isInitializing(res: Response): boolean {\n  return res.status === 503; // SSE endpoint's only 503 is the pre-init canary\n}","tryCatchPattern":"// EventSource reconnects automatically; just don't crash the page on the first 503:\nes.onerror = () => { /* keep the listener; it will succeed after init */ };","preventionTips":["Gate SSE/viewer connections on the health endpoint","Add backoff to custom reconnect loops to avoid 503 bursts during boot","Treat viewer 503 as transient; investigate only if it lasts beyond a minute"],"tags":["http-503","sse","initialization","viewer","retry"],"backgroundTag":"service-startup-not-ready","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}