thedotmack/claude-mem · error · Error
Cannot process observations: memorySessionId not yet capture
Error message
Cannot process observations: memorySessionId not yet captured. This session may need to be reinitialized.
What it means
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.
Source
Thrown at src/services/worker/OpenAICompatibleProvider.ts:202
sessionId: session.sessionDbId, model
});
}
}
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.');
}
const obsPrompt = buildObservationPrompt({
id: 0,
tool_name: message.tool_name!,
tool_input: JSON.stringify(message.tool_input),
tool_output: JSON.stringify(message.tool_response),
created_at_epoch: originalTimestamp ?? Date.now(),
cwd: message.cwd
});
const responseContext = snapshotResponseContext(session);
session.conversationHistory.push({ role: 'user', content: obsPrompt });
session.lastPromptSentAt = Date.now();
session.lastGeneratorSource = 'ingest';
const obsResponse = await this.query(session.conversationHistory, config);
let tokensUsed = 0;View on GitHub (pinned to d768ba3643)
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.
Example fix
// before: observation queued before init resolves
await provider.processObservationMessage(session, msg, worker, config, ts, cwd);
// after: ensure memorySessionId captured first
if (!session.memorySessionId) {
await provider.initializeSession(session, model, config);
}
await provider.processObservationMessage(session, msg, worker, config, ts, cwd); Defensive patterns
Strategy: validation
Validate before calling
// Before calling observation processing, ensure the session is anchored
function isSessionReadyForObservations(session: ActiveSession): boolean {
return typeof session.memorySessionId === 'string' && session.memorySessionId.length > 0;
}
if (!isSessionReadyForObservations(session)) {
await provider.initializeSession(session, model, config);
} Type guard
function hasMemorySessionId(s: ActiveSession): s is ActiveSession & { memorySessionId: string } {
return typeof s.memorySessionId === 'string' && s.memorySessionId.length > 0;
} Try / catch
try {
await provider.processObservationMessage(session, msg, worker, config, ts, cwd);
} catch (err) {
if (err instanceof Error && /memorySessionId not yet captured/.test(err.message)) {
logger.warn('SDK', 'Observation skipped — session not initialized, reinitializing', { id: session.sessionDbId });
await provider.initializeSession(session, model, config);
return; // re-queue or drop
}
throw err;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot process summary: memorySessionId not yet captured. Th
- SSE stream returned HTTP ${response.status}
- ${timeoutMessage} (timed out after ${timeoutMs}ms)
- Failed to get processing status: ${res.status}
- Failed to trigger processing: ${res.status}
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/0f1ea5b456b9eb90.
Report an issue: GitHub.