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

  1. Read the attached error — 'near DROP: syntax error' means SQLite is older than 3.35; upgrade the runtime/driver
  2. Ensure exactly one worker migrates at a time and the DB is writable
  3. Verify afterwards with PRAGMA table_info(pending_messages) that worker_pid is gone
  4. 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

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


AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-08-20). Data as JSON: /api/errors/31ff43c9e2ff90af. Report an issue: GitHub.