mastra-ai/mastra · error

BackgroundTaskWorker: call init() before start()

Error message

BackgroundTaskWorker: call init() before start()

What it means

BackgroundTaskWorker follows a two-phase lifecycle: init(deps) injects the worker's dependencies, then start() begins processing. start() refuses to run when deps were never injected, because the worker would have no storage/logger/manager to operate on. It is a fail-fast guard against incorrect lifecycle usage.

Source

Thrown at packages/core/src/worker/workers/background-task-worker.ts:108

    for (const [name, tool] of Object.entries(tools)) {
      if (!tool || typeof tool.execute !== 'function') continue;
      const execute = tool.execute.bind(tool);
      this.#manager.registerStaticExecutor(name, {
        execute: async (args, options) => {
          return execute(args, {
            toolCallId: '',
            messages: [],
            abortSignal: options?.abortSignal,
          });
        },
      });
    }
  }

  async start(): Promise<void> {
    if (this.#running) return;
    if (!this.deps) {
      throw new Error('BackgroundTaskWorker: call init() before start()');
    }
    // An owned manager has a terminal shutdown lifecycle. Recreate it on a
    // direct stop → start cycle instead of attempting to reinitialize a
    // manager whose subscriptions and executor registry were released.
    if (!this.#manager) {
      this.#createOwnedManager(this.deps);
    }
    const manager = this.#manager;
    if (!manager) {
      throw new Error('BackgroundTaskWorker: failed to initialize background task manager');
    }
    // When sharing Mastra's manager, Mastra has already fired off init() in
    // its constructor as fire-and-forget. Don't re-await it here — that would
    // surface init errors twice (the constructor's `.catch` already reports
    // them) and serialize startWorkers() behind the manager's full bootstrap.
    if (this.#ownsManager) {
      await manager.init(this.deps.pubsub);
    }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Call await worker.init(deps) with a valid WorkerDeps object before start()
  2. Ensure init's returned promise is awaited (deps are set synchronously inside init, but sequence the calls anyway)
  3. If embedding in Mastra, register the worker via Mastra's workers config so the framework performs init for you
  4. Double-check ordering in your bootstrap code: constructor → init → start

Example fix

// before
const worker = new BackgroundTaskWorker({ name: 'tasks' });
await worker.start();
// after
const worker = new BackgroundTaskWorker({ name: 'tasks' });
await worker.init({ mastra, storage, logger, pubsub });
await worker.start();
Defensive patterns

Strategy: try-catch

Validate before calling

if (!worker.deps) await worker.init(deps);

Type guard

function isInitialized(worker) { return !!worker.deps; }

Try / catch

try {
  if (!worker.deps) await worker.init(deps);
  await worker.start();
} catch (e) {
  if (e.message === 'BackgroundTaskWorker: call init() before start()') {
    await worker.init(deps);
    await worker.start();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling worker.start() directly after construction without awaiting worker.init(deps) first, or calling start() before init's promise resolves.

Common situations: Bootstrapping a standalone worker in a script or custom server and forgetting the init() call; copying a start-only snippet from docs; race where start() is invoked concurrently with init() before deps are assigned.

Related errors


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