thedotmack/claude-mem · warning
Failed to drop worker_pid column from pending_messages
Error message
Failed to drop worker_pid column from pending_messages
What it means
Schema migration v32 drops INDEX idx_pending_messages_worker_pid and the worker_pid column from pending_messages. On failure it warns and returns without recording version 32 in schema_versions, so the migration is retried on the next startup. Data is untouched; only the dead column lingers.
Source
Thrown at src/services/sqlite/SessionStore.ts:198
`).get(contentSessionId) as { id: number } | undefined;
return row?.id ?? null;
}
private dropWorkerPidColumn(): void {
const applied = this.db.prepare('SELECT version FROM schema_versions WHERE version = ?').get(32) as SchemaVersion | undefined;
const cols = this.db.query('PRAGMA table_info(pending_messages)').all() as TableColumnInfo[];
const hasColumn = cols.some(c => c.name === 'worker_pid');
if (applied && !hasColumn) return;
if (hasColumn) {
try {
this.db.run('DROP INDEX IF EXISTS idx_pending_messages_worker_pid');
this.db.run('ALTER TABLE pending_messages DROP COLUMN worker_pid');
logger.debug('DB', 'Dropped worker_pid column and its index from pending_messages');
} catch (error) {
logger.warn('DB', 'Failed to drop worker_pid column from pending_messages', {}, error instanceof Error ? error : new Error(String(error)));
return;
}
}
if (!applied) {
this.db.prepare('INSERT OR IGNORE INTO schema_versions (version, applied_at) VALUES (?, ?)').run(32, new Date().toISOString());
}
}
private ensureSDKSessionsPlatformContentIdentity(): void {
const applied = this.db.prepare('SELECT version FROM schema_versions WHERE version = ?').get(33) as SchemaVersion | undefined;
const hasGlobalContentUnique = this.hasUniqueIndexOnColumns('sdk_sessions', ['content_session_id']);
const hasCompositeUnique = this.hasUniqueIndexOnColumns('sdk_sessions', ['platform_source', 'content_session_id']);
const columns = this.db.query('PRAGMA table_info(sdk_sessions)').all() as TableColumnInfo[];
const hasPlatformSource = columns.some(col => col.name === 'platform_source');
if (applied && !hasGlobalContentUnique && hasCompositeUnique && hasPlatformSource) return;
View on GitHub (pinned to 8bc631a71a)
Solutions
- Read the attached error — 'near DROP: syntax error' means SQLite is older than 3.35; upgrade the runtime/driver
- Ensure exactly one worker migrates at a time and the DB is writable
- Verify afterwards with PRAGMA table_info(pending_messages) that worker_pid is gone
- If you cannot upgrade, ignore it: the retry is idempotent and the leftover column is harmless
Defensive patterns
Strategy: fallback
Validate before calling
const { v } = db.prepare('SELECT sqlite_version() AS v').get() as { v: string };
const [maj, min] = v.split('.').map(Number);
const supportsDropColumn = maj > 3 || (maj === 3 && min >= 35);
if (!supportsDropColumn) {
// expect this migration to warn and retry harmlessly; plan to upgrade the runtime
} Prevention
- Run a single worker per DB file so startup migrations never contend
- Keep the runtime's SQLite at 3.35+ when migrations drop columns
- Treat this warning as benign on old SQLite — it retries and mutates nothing on failure
When it happens
Trigger: SQLite older than 3.35.0, which has no ALTER TABLE DROP COLUMN support; the DB locked or read-only when the migration runs; the column referenced by a trigger or view so SQLite refuses the drop.
Common situations: An old runtime bundling an ancient SQLite; a second worker holding the write lock at startup; a DB restored read-only from backup.
Related errors
- Failed to drop dead columns from pending_messages
- SyncApply: could not create or adopt a session for memory_se
- FTS5 not available — user_prompts_fts skipped (search uses C
- Column ${oldCol} not found in ${table}, skipping rename
- Invalid CLAUDE_MEM_QUEUE_ENGINE=${raw}; expected sqlite or b
AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-08-20).
Data as JSON: /api/errors/31ff43c9e2ff90af.
Report an issue: GitHub.