thedotmack/claude-mem · error

CLAUDE_MEM_QUEUE_ENGINE is not "bullmq"

Error message

CLAUDE_MEM_QUEUE_ENGINE is not "bullmq"

What it means

collectBullmqCounts collects BullMQ queue depth statistics by connecting to Redis, but only makes sense when the queue engine is actually BullMQ. It throws this guard error when getRedisQueueConfig().engine is not 'bullmq', protecting against querying BullMQ queues on an installation configured for a different engine.

Solutions

  1. Set CLAUDE_MEM_QUEUE_ENGINE=bullmq in the environment or server config.
  2. If you intentionally use another engine, use the job-count tooling that matches your engine instead of the BullMQ path.
  3. Remove a stale CLAUDE_MEM_QUEUE_ENGINE value so the default engine is used.

Example fix

// before
CLAUDE_MEM_QUEUE_ENGINE=inline claude-mem server-jobs
// after
CLAUDE_MEM_QUEUE_ENGINE=bullmq claude-mem server-jobs
Defensive patterns

Strategy: validation

Validate before calling

const config = await getRedisQueueConfig();
if (config.engine !== 'bullmq') {
  console.warn('Job-count tooling requires CLAUDE_MEM_QUEUE_ENGINE=bullmq');
  return;
}

Type guard

const isBullmq = (c: { engine: string }): c is { engine: 'bullmq' } => c.engine === 'bullmq';

Try / catch

try {
  const counts = await collectBullmqCounts();
} catch (e) {
  if (String(e).includes('not "bullmq"')) {
    console.error('Queue engine is not bullmq; use the matching jobs tooling.');
  }
}

Prevention

When it happens

Trigger: Calling the server-jobs command (which invokes collectBullmqCounts) while CLAUDE_MEM_QUEUE_ENGINE (or equivalent config) resolves to a non-bullmq engine in getRedisQueueConfig().

Common situations: Developer switched the queue engine to a non-BullMQ implementation but still runs jobs-inspection tooling that assumes BullMQ; stale environment variable from an older setup.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/npx-cli/commands/server-jobs.ts:511

}> {
  if (testSeams.openPool) return testSeams.openPool();
  const { getSharedPostgresPool } = await import('../../storage/postgres/index.js');
  const pool = getSharedPostgresPool({ requireDatabaseUrl: true });
  return {
    pool: pool as never,
    releasePool: async () => { /* shared pool tears down on process exit */ },
  };
}

// BullMQ access. Direct construction avoids importing the runtime, keeping
// the CLI fast to boot. Returns counts per known queue name; gracefully
// returns null when Redis is unconfigured.
async function collectBullmqCounts(): Promise<Record<string, { waiting: number; active: number; completed: number; failed: number; delayed: number; stalled: number }>> {
  const { getRedisQueueConfig } = await import('../../server/queue/redis-config.js');
  const { Queue } = await import('bullmq');
  const config = getRedisQueueConfig();
  if (config.engine !== 'bullmq') {
    throw new Error('CLAUDE_MEM_QUEUE_ENGINE is not "bullmq"');
  }
  const { SERVER_JOB_QUEUE_NAMES } = await import('../../server/jobs/types.js');
  const out: Record<string, { waiting: number; active: number; completed: number; failed: number; delayed: number; stalled: number }> = {};
  for (const [kind, name] of Object.entries(SERVER_JOB_QUEUE_NAMES)) {
    const queue = new Queue(name, { connection: config.connection, prefix: config.prefix });
    try {
      const counts = await queue.getJobCounts('waiting', 'active', 'completed', 'failed', 'delayed');
      out[kind] = {
        waiting: Number(counts.waiting ?? 0),
        active: Number(counts.active ?? 0),
        completed: Number(counts.completed ?? 0),
        failed: Number(counts.failed ?? 0),
        delayed: Number(counts.delayed ?? 0),
        stalled: 0, // BullMQ rotates the stalled list; runtime tracks it via QueueEvents.
      };
    } finally {
      await queue.close();
    }

View on GitHub (pinned to d8bc9755e7)