{"record":{"id":"0f1ea5b456b9eb90","repo":"thedotmack/claude-mem","slug":"cannot-process-observations-memorysessionid-not-y","errorCode":null,"errorMessage":"Cannot process observations: memorySessionId not yet captured. This session may need to be reinitialized.","messagePattern":"Cannot process observations: memorySessionId not yet captured\\. This session may need to be reinitialized\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/worker/OpenAICompatibleProvider.ts","lineNumber":202,"sourceCode":"        sessionId: session.sessionDbId, model\n      });\n    }\n  }\n\n  private async processObservationMessage(\n    session: ActiveSession,\n    message: { prompt_number?: number; tool_name?: string; tool_input?: unknown; tool_response?: unknown; cwd?: string },\n    worker: WorkerRef | undefined,\n    config: TConfig,\n    originalTimestamp: number | null,\n    lastCwd: string | undefined\n  ): Promise<void> {\n    if (message.prompt_number !== undefined) {\n      session.lastPromptNumber = message.prompt_number;\n    }\n\n    if (!session.memorySessionId) {\n      throw new Error('Cannot process observations: memorySessionId not yet captured. This session may need to be reinitialized.');\n    }\n\n    const obsPrompt = buildObservationPrompt({\n      id: 0,\n      tool_name: message.tool_name!,\n      tool_input: JSON.stringify(message.tool_input),\n      tool_output: JSON.stringify(message.tool_response),\n      created_at_epoch: originalTimestamp ?? Date.now(),\n      cwd: message.cwd\n    });\n    const responseContext = snapshotResponseContext(session);\n\n    session.conversationHistory.push({ role: 'user', content: obsPrompt });\n    session.lastPromptSentAt = Date.now();\n    session.lastGeneratorSource = 'ingest';\n    const obsResponse = await this.query(session.conversationHistory, config);\n\n    let tokensUsed = 0;","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/worker/OpenAICompatibleProvider.ts#L184-L220","documentation":"Thrown by processObservationMessage when an ingest/observation message arrives for an ActiveSession whose memorySessionId has not yet been captured. memorySessionId is set during session initialization from the provider's first response; downstream observation processing needs it to scope the prompt. The guard prevents building an observation prompt against an unanchored session.","triggerScenarios":"A tool observation message is enqueued and dispatched to processObservationMessage before session initialization completed (or after it failed silently). Concretely: session.memorySessionId is null/undefined when the worker drains the observation queue.","commonSituations":"Worker restart mid-session where in-memory state was rebuilt without the captured id; init response returned empty content (logger.error 'Empty ... init response') so session_id was never recorded; a race where the observation arrives during the init handshake; session restored from DB but the memorySessionId column was null.","solutions":["Reinitialize the session so the init handshake captures memorySessionId before observations are processed.","Check worker logs for 'Empty <provider> init response - session may lack context' which indicates why the id was never set.","Verify the session row in the DB has a non-null memory_session_id; if lost, restart the worker to trigger re-init.","If reproducing in tests, ensure the provider mock returns a session_id in the init response before queueing observation messages."],"exampleFix":"// before: observation queued before init resolves\nawait provider.processObservationMessage(session, msg, worker, config, ts, cwd);\n\n// after: ensure memorySessionId captured first\nif (!session.memorySessionId) {\n  await provider.initializeSession(session, model, config);\n}\nawait provider.processObservationMessage(session, msg, worker, config, ts, cwd);","handlingStrategy":"validation","validationCode":"// Before calling observation processing, ensure the session is anchored\nfunction isSessionReadyForObservations(session: ActiveSession): boolean {\n  return typeof session.memorySessionId === 'string' && session.memorySessionId.length > 0;\n}\nif (!isSessionReadyForObservations(session)) {\n  await provider.initializeSession(session, model, config);\n}","typeGuard":"function hasMemorySessionId(s: ActiveSession): s is ActiveSession & { memorySessionId: string } {\n  return typeof s.memorySessionId === 'string' && s.memorySessionId.length > 0;\n}","tryCatchPattern":"try {\n  await provider.processObservationMessage(session, msg, worker, config, ts, cwd);\n} catch (err) {\n  if (err instanceof Error && /memorySessionId not yet captured/.test(err.message)) {\n    logger.warn('SDK', 'Observation skipped — session not initialized, reinitializing', { id: session.sessionDbId });\n    await provider.initializeSession(session, model, config);\n    return; // re-queue or drop\n  }\n  throw err;\n}","preventionTips":["Always complete initializeSession (and verify memorySessionId is set) before enqueuing observation/summary messages.","Log when init returns empty content so a missing id is visible immediately.","In worker restart paths, re-run init rather than assuming persisted state has the id."],"tags":["session-state","worker","openai-provider","initialization"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}