mastra-ai/mastra · error

GithubReconcileWorker: call init() before start()

Error message

GithubReconcileWorker: call init() before start()

What it means

GithubReconcileWorker.start() requires init(deps) to have been called first, since start() reads this.deps (logger, pubsub) to run boot sweeps and scheduling. If start() is called before init() and the worker isn't already running, it throws this explicit lifecycle error instead of failing later with an opaque undefined-deps crash.

Source

Thrown at mastracode/factory/src/integrations/github/reconcile-worker.ts:94

    this.#issueIntervalMs = config.issueIntervalMs ?? this.#intervalMs;
    if (!Number.isFinite(this.#intervalMs) || this.#intervalMs <= 0) {
      throw new Error('GitHub pull request reconcile interval must be a positive number.');
    }
    if (!Number.isFinite(this.#issueIntervalMs) || this.#issueIntervalMs <= 0) {
      throw new Error('GitHub issue reconcile interval must be a positive number.');
    }
    this.#leaseTtlMs = Math.max(MIN_LEASE_TTL_MS, Math.min(this.#intervalMs, this.#issueIntervalMs) * 3);
    this.#now = config.now ?? Date.now;
  }

  async init(deps: WorkerDeps): Promise<void> {
    await super.init(deps);
    this.#leaseProvider = getLeaseProvider(deps.pubsub);
  }

  async start(): Promise<void> {
    if (this.#running) return;
    if (!this.deps) throw new Error('GithubReconcileWorker: call init() before start()');
    this.#running = true;
    this.deps.logger.info('GitHub reconcile worker started', {
      pullRequestIntervalMs: this.#reconcile ? this.#intervalMs : undefined,
      issueIntervalMs: this.#reconcileIssues ? this.#issueIntervalMs : undefined,
    });
    // Sweep on boot: a restart is exactly when webhooks were most likely missed.
    this.#schedule(0);
  }

  async stop(): Promise<void> {
    if (!this.#running) return;
    this.#running = false;
    if (this.#timer) clearTimeout(this.#timer);
    this.#timer = undefined;
    await this.#inFlight;
  }

  get isRunning(): boolean {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Call `await worker.init(deps)` (with logger and pubsub) before `await worker.start()`.
  2. Check startup ordering so the module that starts the worker also performs init.
  3. In tests, use the same fixture/deps helper used elsewhere to init before start.

Example fix

// before
const worker = new GithubReconcileWorker(config);
await worker.start();
// after
const worker = new GithubReconcileWorker(config);
await worker.init({ logger, pubsub });
await worker.start();
Defensive patterns

Strategy: validation

Validate before calling

if (!worker.isInitialized?.() && !workerHasDeps) await worker.init(deps); // or track init yourself
let inited = false;
async function startWorker(w, deps) { if (!inited) { await w.init(deps); inited = true; } await w.start(); }

Type guard

function isInitialized(w: GithubReconcileWorker): boolean { return 'deps' in w && (w as { deps?: unknown }).deps !== undefined; }

Try / catch

try {
  await worker.start();
} catch (err) {
  if (err instanceof Error && err.message.includes('call init() before start()')) {
    await worker.init(deps);
    await worker.start();
  } else throw err;
}

Prevention

When it happens

Trigger: Calling `worker.start()` directly after `new GithubReconcileWorker(...)` without a preceding `await worker.init(deps)`; or calling start() on a second instance that never got init (a first instance with init returns early via `if (this.#running) return;`).

Common situations: Wiring the worker in a DI/bootstrap file where construction and start happen in different modules and the init step was dropped during refactoring; tests instantiating the worker and calling start() without fixture deps.

Related errors


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