mastra-ai/mastra · warning

Broker election in progress by another process

Error message

Broker election in progress by another process

What it means

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.

Source

Thrown at packages/core/src/events/unix-socket-pubsub.ts:454

   */
  async #electBroker(): Promise<void> {
    const lockPath = this.socketPath + '.elect';
    let lockFd: FileHandle | undefined;
    try {
      lockFd = await open(lockPath, 'wx');
    } catch (e) {
      if ((e as NodeJS.ErrnoException).code === 'EEXIST') {
        if (await this.#isElectionLockStale(lockPath)) {
          await unlink(lockPath).catch(() => {});
          throw new Error('Stale broker election lock removed');
        }
        await new Promise(resolve => setTimeout(resolve, 150));
        try {
          await this.#connectClient();
          this.#throwIfClosed();
          return;
        } catch {
          throw new Error('Broker election in progress by another process');
        }
      }
      throw e;
    }

    try {
      // Re-check: a previous election round may have installed a broker
      // between our initial connectClient() and acquiring this lock.
      try {
        await this.#connectClient();
        this.#throwIfClosed();
        return;
      } catch {
        // Still no live broker — proceed with election.
      }
      await unlink(this.socketPath).catch(() => {});
      this.#throwIfClosed();
      await this.#listen();

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Retry the publish/subscribe with backoff until the other process finishes election and binds the broker
  2. Increase startup timeout / retry count around first use
  3. 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)
  4. Ensure all processes use the same socket path and have consistent clocks so staleness detection works

Example fix

// before
await pubsub.publish("t", e); // threw during simultaneous startup
// after
let err;
for (let i = 0; i < 5; i++) {
  try { await pubsub.publish("t", e); err = null; break; }
  catch (e) { err = e; await new Promise(r => setTimeout(r, 200 * (i + 1))); }
}
if (err) throw err;
Defensive patterns

Strategy: retry

Validate before calling

// only one process should attempt election first
if (isPrimaryInstance()) {
  await pubsub.publish('boot', {}); // triggers/finishes election
}
await waitForBrokerReady(socketPath, { timeoutMs: 5000 });

Try / catch

try {
  await pubsub.subscribe(topic, cb);
} catch (e) {
  if (e.message === 'Broker election in progress by another process') {
    await backoff(attempt); // election resolves shortly; retry
    return retry(attempt + 1);
  }
  throw e;
}

Prevention

When it happens

Trigger: #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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/77f7f3ba63b78405. Report an issue: GitHub.