{"record":{"id":"0ca67fb62119541c","repo":"thedotmack/claude-mem","slug":"serverjobqueue-this-name-is-already-started","errorCode":null,"errorMessage":"ServerJobQueue ${this.name} is already started","messagePattern":"ServerJobQueue (.+?) is already started","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/server/jobs/ServerJobQueue.ts","lineNumber":247,"sourceCode":"    }\n  }\n\n  // Single source of truth for queue-side error accounting. worker errors and\n  // QueueEvents errors both increment counters.errored and notify listeners,\n  // so per-process metrics aren't asymmetric across the two sources.\n  private notifyQueueError(error: unknown, source: 'worker' | 'queue-events'): void {\n    this.counters.errored += 1;\n    logger.warn('QUEUE', `${this.name} ${source} error`, {\n      error: error instanceof Error ? error.message : String(error),\n    });\n    for (const l of this.listeners) {\n      try { l.onError?.(error); } catch { /* listener errors must not propagate */ }\n    }\n  }\n\n  start(processor: Processor<TPayload>): void {\n    if (this.started) {\n      throw new Error(`ServerJobQueue ${this.name} is already started`);\n    }\n    const workerOptions: WorkerOptions = {\n      connection: this.config.connection,\n      prefix: this.config.prefix,\n      autorun: false,\n      concurrency: this.concurrency,\n      lockDuration: this.lockDurationMs\n    };\n    const worker = this.workerFactory\n      ? this.workerFactory(this.name, processor, workerOptions)\n      : new Worker<TPayload>(this.name, processor, workerOptions);\n    worker.on('error', (error: unknown) => this.notifyQueueError(error, 'worker'));\n    // BullMQ Worker exposes `active`, `completed`, `failed`, `progress`, and\n    // `stalled` events. We attach to all five because the runtime relies on\n    // them for observability (Phase 12).\n    if (typeof (worker as { on?: unknown }).on === 'function') {\n      const w = worker as Worker<TPayload>;\n      w.on('active', (job: Job<TPayload>) => {","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/server/jobs/ServerJobQueue.ts#L229-L265","documentation":"ServerJobQueue.start() wires up the BullMQ worker/processor, which can only be attached once per queue instance. Calling start() again on an instance whose `started` flag is already true throws this error to prevent a second worker from being created.","triggerScenarios":"Calling start(processor) twice on the same ServerJobQueue instance, e.g. re-initializing after a hot reload, restart routine, or retry path without constructing a new queue.","commonSituations":"Dev-server hot module reload re-running startup code; a retry wrapper calling start again after a partial failure; duplicated initialization in both server bootstrap and a plugin hook.","solutions":["Call start() exactly once per ServerJobQueue instance; guard the call site with an initialization flag","Check the queue's started state (or your own flag) before invoking start","Create a fresh ServerJobQueue instance if a full re-init is required"],"exampleFix":"// before\nqueue.start(processor);\n// after (hot-reload safe)\nif (!queueStarted) {\n  queue.start(processor);\n  queueStarted = true;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  queue.start(processor);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('is already started')) {\n    return; // idempotent: queue already running\n  }\n  throw e;\n}","preventionTips":["Call start() only from one initialization path (single bootstrap module)","Track started state in an app-level singleton flag","Avoid calling start() inside hot-reloadable or retried code blocks"],"tags":["lifecycle","jobs","double-initialization","state"],"backgroundTag":"invalid-state-transition","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}