thedotmack/claude-mem · error · Error

Cannot process observations: memorySessionId not yet…

Error message

Cannot process observations: memorySessionId not yet captured. This session may need to be reinitialized.

What it means

OpenAICompatibleProvider.processObservationMessage requires session.memorySessionId to be set before it can persist observations, because observations must attach to a memory session record. If ingest has not yet captured the session id (e.g. session creation response never arrived), it throws and asks the user to reinitialize the session.

Solutions

  1. Reinitialize the session so a new memorySessionId is captured, then resend.
  2. Check logs/network for a failed session-creation API call and fix that root cause.
  3. Ensure observation messages are only sent after the session-created acknowledgment.
  4. Restart the worker/agent session if the id was lost mid-run.

Example fix

// before
await processObservationMessage(message, session);
// after
if (!session.memorySessionId) {
  session.memorySessionId = await createMemorySession(session); // re-init first
}
await processObservationMessage(message, session);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!session.memorySessionId) await initializeMemorySession(session);

Try / catch

try { await provider.runMessageLoop(session, msg); } catch (e) { if (e.message.includes('memorySessionId not yet captured')) { await reinitializeSession(session); } }

Prevention

When it happens

Trigger: A message with observations arrives in runMessageLoop while session.memorySessionId is still falsy — the session-start handshake failed, the create-session response was lost, or observations raced ahead of session initialization.

Common situations: Network/API failure during session creation; worker restarted mid-session losing the captured id; provider sending observation messages before the first session acknowledgment; bug in session init ordering.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/0f1ea5b456b9eb90. Report an issue: GitHub.

Appendix: source

Thrown at src/services/worker/OpenAICompatibleProvider.ts:275

    // that never happened. Keep the turn so role alternation holds, but never
    // hand it to the storage path.
    session.conversationHistory.push({ role: 'assistant', content: initResponse.content || '' });
  }

  private async processObservationMessage(
    session: ActiveSession,
    message: { prompt_number?: number; tool_name?: string; tool_input?: unknown; tool_response?: unknown; cwd?: string },
    worker: WorkerRef | undefined,
    config: TConfig,
    originalTimestamp: number | null,
    lastCwd: string | undefined
  ): Promise<void> {
    if (message.prompt_number !== undefined) {
      session.lastPromptNumber = message.prompt_number;
    }

    if (!session.memorySessionId) {
      throw new Error('Cannot process observations: memorySessionId not yet captured. This session may need to be reinitialized.');
    }

    // Retire a full generation BEFORE sending, so the request that would cross
    // the ceiling is never paid for. The batch is preserved and drained by the
    // fresh generation the next ingest starts (#3800).
    if (shouldRecycleConversation(session.conversationHistory, this.conversationMaxChars())) {
      await recycleObserverConversation(
        session,
        this.sessionManager,
        worker,
        'budget',
        `conversation reached ${conversationChars(session.conversationHistory)} chars`,
      );
      return;
    }

    // An oversized payload is condensed by a bounded model pass before the
    // prompt is built, so the observation carries a summary of the whole field

View on GitHub (pinned to d8bc9755e7)