thedotmack/claude-mem · warning
Service initializing
Error message
Service initializing
What it means
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.
Source
Thrown at src/services/worker/http/routes/ViewerRoutes.ts:81
});
});
private handleViewerUI = this.wrapHandler((req: Request, res: Response): void => {
if (!viewerHtmlBytes) {
throw new Error('Viewer UI not found at any expected location');
}
res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.send(viewerHtmlBytes);
});
private handleSSEStream = this.wrapHandler((req: Request, res: Response): void => {
try {
this.dbManager.getSessionStore();
} catch (initError: unknown) {
if (initError instanceof Error) {
logger.warn('HTTP', 'SSE stream requested before DB initialization', {}, initError);
}
res.status(503).json({ error: 'Service initializing' });
return;
}
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
this.sseBroadcaster.addClient(res);
const projectCatalog = this.dbManager.getSessionStore().getProjectCatalog();
this.sseBroadcaster.broadcast({
type: 'initial_load',
projects: projectCatalog.projects,
sources: projectCatalog.sources,
projectsBySource: projectCatalog.projectsBySource,
timestamp: Date.now()
});
View on GitHub (pinned to e2d1df569a)
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)
Example fix
// before
const es = new EventSource(`${base}/sse`); // 503 during boot, no retry logic
// after
async function connectWhenReady() {
while (!(await fetch(`${base}/api/health`).then(r => r.ok).catch(() => false)))
await new Promise(r => setTimeout(r, 500));
return new EventSource(`${base}/sse`);
} Defensive patterns
Strategy: retry
Validate before calling
while (!(await fetch(`${base}/api/health`).then(r => r.ok).catch(() => false)))
await new Promise(r => setTimeout(r, 500));
const es = new EventSource(`${base}/sse`); // connect only after readiness Type guard
function isInitializing(res: Response): boolean {
return res.status === 503; // SSE endpoint's only 503 is the pre-init canary
} Try / catch
// EventSource reconnects automatically; just don't crash the page on the first 503:
es.onerror = () => { /* keep the listener; it will succeed after init */ }; Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Service initializing
- ViewerUnavailable
- chroma-mcp transport error during "${toolName}" (retry faile
- Chroma query failed - connection lost: ${errorMessage}
- sync hub push ${res.status}: ${body}
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/8538a8b9afd027fe.
Report an issue: GitHub.