{"record":{"id":"3a2c302d20c97063","repo":"thedotmack/claude-mem","slug":"service-initializing","errorCode":"Service initializing","errorMessage":"Database is still initializing, please retry","messagePattern":"Database is still initializing, please retry","errorType":"http","errorClass":null,"httpStatus":503,"severity":"warning","filePath":"src/services/worker-service.ts","lineNumber":347,"sourceCode":"    this.server.app.use(['/api', '/v1'], async (req, res, next) => {\n      if (\n        req.path === '/chroma/status' ||\n        req.path === '/health' ||\n        req.path === '/readiness' ||\n        req.path === '/version' ||\n        req.path === '/settings/dependency-health'\n      ) {\n        next();\n        return;\n      }\n\n      if (this.initializationCompleteFlag) {\n        next();\n        return;\n      }\n\n      logger.debug('WORKER', `Request to ${req.method} ${req.path} rejected — DB not initialized`);\n      res.status(503).json({\n        error: 'Service initializing',\n        message: 'Database is still initializing, please retry'\n      });\n      return;\n    });\n\n    this.server.registerRoutes(new ViewerRoutes(this.sseBroadcaster, this.dbManager, this.sessionManager));\n    const sessionRoutes = new SessionRoutes(this.sessionManager, this.dbManager, this.sdkAgent, this.geminiAgent, this.openRouterAgent, this.sessionEventBroadcaster, this, this.completionHandler);\n    this.server.registerRoutes(sessionRoutes);\n    attachIngestGeneratorStarter((sessionDbId, source) =>\n      sessionRoutes.ensureGeneratorRunning(sessionDbId, source),\n    );\n    this.server.registerRoutes(new DataRoutes(this.paginationHelper, this.dbManager, this.sessionManager, this.sseBroadcaster, this, this.startTime));\n    this.server.registerRoutes(new SettingsRoutes(this.settingsManager));\n    this.server.registerRoutes(new LogsRoutes());\n    this.server.registerRoutes(new MemoryRoutes(this.dbManager, 'claude-mem'));\n    this.server.registerRoutes(new ServerV1Routes({\n      getDatabase: () => this.dbManager.getConnection(),","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/services/worker-service.ts#L329-L365","documentation":"HTTP 503 returned by a global middleware on the worker's /api and /v1 route trees when a request arrives before the database initialization completes (initializationCompleteFlag is false). It is a startup gate, not a fault: only /health, /readiness, /version, /chroma/status and /settings/dependency-health are exempt and always served. The body carries error 'Service initializing' with an explicit instruction to retry.","triggerScenarios":"Any API call to /api/* or /v1/* issued between worker listen() and the end of DB initialization (session store open, migrations, Chroma boot). Typically a client fires requests immediately after spawning the worker instead of waiting for readiness.","commonSituations":"Scripts that start `claude-mem worker` and instantly call search/session endpoints; restarts on large databases where init takes seconds-to-minutes; health-checkers probing a non-exempt path; CI that treats 503 as fatal instead of retrying.","solutions":["Retry the same request with exponential backoff (the condition is transient and self-clearing once init finishes)","Poll the exempt GET /api/health or /api/readiness endpoint until it reports ready before issuing other calls","If 503 persists past a minute, check worker logs for a stuck initialization (locked SQLite file, missing uv/Chroma deps)"],"exampleFix":"// before\nconst res = await fetch('http://127.0.0.1:37777/api/sessions');\nconst data = await res.json(); // 503 during boot\n\n// after\nasync function waitReady(base: string) {\n  for (let i = 0; i < 30; i++) {\n    const h = await fetch(`${base}/api/health`);\n    if (h.ok) return;\n    await new Promise(r => setTimeout(r, 1000));\n  }\n  throw new Error('worker not ready after 30s');\n}\nawait waitReady(base);\nconst res = await fetch(`${base}/api/sessions`);","handlingStrategy":"retry","validationCode":"async function workerReady(base: string): Promise<boolean> {\n  try {\n    const r = await fetch(`${base}/api/health`); // exempt from the init gate\n    return r.ok;\n  } catch { return false; }\n}","typeGuard":"function isInitializingResponse(body: unknown, status: number): boolean {\n  return status === 503 &&\n    typeof body === 'object' && body !== null &&\n    (body as { error?: string }).error === 'Service initializing';\n}","tryCatchPattern":"for (let attempt = 0; attempt < 10; attempt++) {\n  const res = await callApi();\n  if (res.status !== 503) return handle(res);\n  await sleep(500 * 2 ** attempt);\n}\nthrow new Error('worker still initializing after retries');","preventionTips":["Always gate client startup on GET /api/health before the first real request","Treat 503 'Service initializing' as backoff-signal, never as a fatal error in health checks","In tests, await the readiness endpoint instead of a fixed sleep after spawning the worker"],"tags":["http-503","startup","initialization","worker","retry"],"backgroundTag":"service-startup-not-ready","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}