{"record":{"id":"77f7f3ba63b78405","repo":"mastra-ai/mastra","slug":"broker-election-in-progress-by-another-process","errorCode":null,"errorMessage":"Broker election in progress by another process","messagePattern":"Broker election in progress by another process","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/core/src/events/unix-socket-pubsub.ts","lineNumber":454,"sourceCode":"   */\n  async #electBroker(): Promise<void> {\n    const lockPath = this.socketPath + '.elect';\n    let lockFd: FileHandle | undefined;\n    try {\n      lockFd = await open(lockPath, 'wx');\n    } catch (e) {\n      if ((e as NodeJS.ErrnoException).code === 'EEXIST') {\n        if (await this.#isElectionLockStale(lockPath)) {\n          await unlink(lockPath).catch(() => {});\n          throw new Error('Stale broker election lock removed');\n        }\n        await new Promise(resolve => setTimeout(resolve, 150));\n        try {\n          await this.#connectClient();\n          this.#throwIfClosed();\n          return;\n        } catch {\n          throw new Error('Broker election in progress by another process');\n        }\n      }\n      throw e;\n    }\n\n    try {\n      // Re-check: a previous election round may have installed a broker\n      // between our initial connectClient() and acquiring this lock.\n      try {\n        await this.#connectClient();\n        this.#throwIfClosed();\n        return;\n      } catch {\n        // Still no live broker — proceed with election.\n      }\n      await unlink(this.socketPath).catch(() => {});\n      this.#throwIfClosed();\n      await this.#listen();","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/events/unix-socket-pubsub.ts#L436-L472","documentation":"If the election lock file exists but is NOT stale, another live process is currently running broker election. After a short 150ms wait the process tries to connect as a client; if that fails it throws this error indicating the election is still in progress elsewhere.","triggerScenarios":"#electBroker (from #start): open(lockPath,'wx') fails with EEXIST, #isElectionLockStale is false, the 150ms-delayed #connectClient attempt fails, so no broker is available yet and the lock is actively held by another process.","commonSituations":"Many processes starting simultaneously against a fresh socket path, slow election in the peer process (slow disk/loads), retry logic giving up before the other process finishes binding the broker.","solutions":["Retry the publish/subscribe with backoff until the other process finishes election and binds the broker","Increase startup timeout / retry count around first use","Investigate why the electing process is slow or whether it died leaving a lock the staleness check considers fresh (e.g. very short staleness window vs clock skew)","Ensure all processes use the same socket path and have consistent clocks so staleness detection works"],"exampleFix":"// before\nawait pubsub.publish(\"t\", e); // threw during simultaneous startup\n// after\nlet err;\nfor (let i = 0; i < 5; i++) {\n  try { await pubsub.publish(\"t\", e); err = null; break; }\n  catch (e) { err = e; await new Promise(r => setTimeout(r, 200 * (i + 1))); }\n}\nif (err) throw err;","handlingStrategy":"retry","validationCode":"// only one process should attempt election first\nif (isPrimaryInstance()) {\n  await pubsub.publish('boot', {}); // triggers/finishes election\n}\nawait waitForBrokerReady(socketPath, { timeoutMs: 5000 });","typeGuard":null,"tryCatchPattern":"try {\n  await pubsub.subscribe(topic, cb);\n} catch (e) {\n  if (e.message === 'Broker election in progress by another process') {\n    await backoff(attempt); // election resolves shortly; retry\n    return retry(attempt + 1);\n  }\n  throw e;\n}","preventionTips":["Retry with exponential backoff (e.g. 200ms, 400ms, 800ms) during multi-process startup","Stagger instance startup (readiness gates) so one process elects first","Investigate slow election in the peer process if retries exhaust","Ensure lock staleness detection has correct clocks; avoid large clock skew between hosts"],"tags":["pubsub","unix-socket","broker-election","lock-contention","retry"],"backgroundTag":"broker-election-lock-contention","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}