thedotmack/claude-mem · error
SyncApply: could not create or adopt a session for memory_se
Error message
SyncApply: could not create or adopt a session for memory_session_id=${memorySessionId} What it means
Thrown in ensureSessionForMemoryId when neither creating a stub sdk_session nor adopting an existing one succeeded. The INSERT ... ON CONFLICT(platform_source, content_session_id) DO NOTHING returned nothing (a conflicting row already owns that content id), and the follow-up SELECT by (platform_source, content_session_id) found no row. This is an inconsistent state: the conflict blocked insert, yet no row matches the conflicting key.
Source
Thrown at src/services/sync/SyncApply.ts:693
(content_session_id, memory_session_id, project, platform_source, user_prompt, started_at, started_at_epoch, status)
VALUES (?, ?, ?, ?, NULL, ?, ?, 'completed')
ON CONFLICT(platform_source, content_session_id) DO NOTHING
RETURNING id
`).get(content, memorySessionId, project, platform, iso, createdAtEpoch) as { id: number } | null;
let sessionId: number;
if (inserted) {
logger.debug('SYNC_APPLY', 'Created stub sdk_session for remote memory session', {
memorySessionId,
project,
});
sessionId = inserted.id;
} else {
const adopted = this.db.prepare(
'SELECT id FROM sdk_sessions WHERE platform_source = ? AND content_session_id = ?'
).get(platform, content) as { id: number } | undefined;
if (!adopted) {
throw new Error(`SyncApply: could not create or adopt a session for memory_session_id=${memorySessionId}`);
}
sessionId = adopted.id;
}
this.claimParkedTitle(sessionId, SyncApply.parkedTitleMemKey(memorySessionId));
if (contentSessionId) {
this.claimParkedTitle(sessionId, SyncApply.parkedTitleContentKey(platform, contentSessionId));
}
return sessionId;
}
private applyObservation(op: SyncOp, body: Record<string, unknown>, chromaJobs: ChromaJob[]): 'applied' | 'stale' {
const memorySessionId = fieldString(op, body, 'memory_session_id');
const project = fieldString(op, body, 'project');
const type = fieldString(op, body, 'type');
const createdAtEpoch = fieldNumber(op, body, 'created_at_epoch');
if (!memorySessionId || !project || !type || createdAtEpoch === null) {
throw invalidOp(op, 'observation body requires memory_session_id, project, type, created_at_epoch');View on GitHub (pinned to d768ba3643)
Solutions
- Verify the (platform_source, content_session_id) unique index exists and matches the SELECT predicate exactly (migration v33).
- Check that the `platform` and `content` variables passed to the SELECT equal the values the INSERT used (normalization must be identical).
- Look for a concurrent delete/rollback on sdk_sessions between the INSERT and SELECT; wrap the resolution in the same transaction consistently.
- Run the DB integrity check / re-run pending migrations to repair schema state.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-resolve the session id the same way ensureSessionForMemoryId does,
// to surface the inconsistency before batch apply:
function preresolveSession(db: Database, platform: string, content: string): number | undefined {
return (db.prepare('SELECT id FROM sdk_sessions WHERE platform_source=? AND content_session_id=?')
.get(platform, content) as { id: number } | undefined)?.id;
} Try / catch
try { apply.applyOps(page, opts); }
catch (e) {
if (e instanceof Error && e.message.startsWith('SyncApply: could not create or adopt a session')) {
// schema/constraint drift or concurrent delete — investigate, skip op
logger.error('SYNC_APPLY', e.message); return;
}
throw e;
} Prevention
- Run all DB migrations (esp. v33 unique index) before enabling sync apply.
- Normalize platform_source identically in INSERT and SELECT paths.
- Avoid concurrent deletes of sdk_sessions during a sync-apply batch.
When it happens
Trigger: applyObservation/applyCanonicalRowOp resolves a memory_session_id to a local sdk_session. The INSERT is blocked by the unique (platform_source, content_session_id) constraint, then `SELECT id FROM sdk_sessions WHERE platform_source=? AND content_session_id=?` returns undefined. Should not happen if the constraint and the select key agree.
Common situations: Schema drift between the unique index columns and the SELECT columns (e.g. platform normalization differs between insert and select), a concurrent transaction that deleted the conflicting row between insert and select, a partial/failed migration (v33) leaving the constraint without matching rows, or a platform_source value normalized differently in the two statements.
Related errors
- SyncApply: sequence gap (expected ${incrementCanonicalDecima
- SyncApply: ops out of order (seq ${op.seq} after ${lastSeq})
- CLAUDE_MEM_SERVER_DATABASE_URL is required for `server ${com
- server startup configuration is invalid: - ${line}
- Cannot bootstrap server API key: CLAUDE_MEM_SERVER_DATABASE_
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/7e63e380169ffe7f.
Report an issue: GitHub.