mastra-ai/mastra · error

Factory storage domain '${this.name}' is already bound to an

Error message

Factory storage domain '${this.name}' is already bound to another storage instance

What it means

A FactoryStorageDomain instance can only ever be attached to one FactoryStorage instance. __bindFactoryStorage (called from FactoryStorage.registerDomain) throws if the domain is already bound to a different storage, preventing cross-instance leakage where a domain would read/write the wrong backing storage.

Source

Thrown at packages/core/src/storage/factory-storage.ts:230

 * Base class for application domains owned by a {@link FactoryStorage}.
 * Domains are bound once when registered and share their owner's connection.
 */
export abstract class FactoryStorageDomain extends StorageDomain {
  override readonly name: string;
  #storage?: FactoryStorage;

  protected constructor(name: string) {
    if (!name.trim()) {
      throw new Error('Factory storage domain name must not be empty');
    }
    super({ component: 'STORAGE', name });
    this.name = name;
  }

  /** @internal Bound by {@link FactoryStorage.registerDomain}. */
  __bindFactoryStorage(storage: FactoryStorage): void {
    if (this.#storage && this.#storage !== storage) {
      throw new Error(`Factory storage domain '${this.name}' is already bound to another storage instance`);
    }
    this.#storage = storage;
  }

  protected get storage(): FactoryStorage {
    if (!this.#storage) {
      throw new Error(`Factory storage domain '${this.name}' has not been registered`);
    }
    return this.#storage;
  }

  /**
   * Initialize this domain (via its owning storage) if it hasn't been yet.
   * Lets consumers holding a domain handle run the same fail-soft readiness
   * check as {@link FactoryStorage.ensureDomainReady} without also needing a
   * reference to the storage backend.
   */
  ensureReady(): Promise<void> {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Create a fresh domain instance per FactoryStorage instead of sharing one
  2. If rebinding is intentional, construct a new domain rather than reusing the bound one
  3. Audit DI/test setup so each storage gets its own set of domains (factory functions help: () => new WorkspacesDomain())
  4. Check for duplicate module instantiation (double imports / ESM+CJS mixing) producing two FactoryStorage instances

Example fix

// before
const workspaces = new WorkspacesDomain();
await storageA.registerDomain(workspaces);
await storageB.registerDomain(workspaces); // throws
// after
await storageA.registerDomain(new WorkspacesDomain());
await storageB.registerDomain(new WorkspacesDomain());
Defensive patterns

Strategy: try-catch

Validate before calling

function canBind(domain: FactoryStorageDomain, storage: FactoryStorage): boolean {
  // attempt binding on a throwaway basis via the public registerDomain API in tests
  return !(domain as unknown as { #storage?: FactoryStorage }).hasOwnProperty?.('storage');
}

Try / catch

try {
  await storage.registerDomain(domain);
} catch (err) {
  if (err instanceof Error && err.message.includes('already bound to another storage instance')) {
    await storage.registerDomain(new (domain.constructor as new () => typeof domain)());
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Registering the same domain instance with two different FactoryStorage instances; reusing a singleton domain across two Mastra storages; re-registering domains after replacing the storage object in tests; accidentally exporting one domain instance and importing it in two configurations.

Common situations: Test setups that build multiple FactoryStorage instances but share domain instances; hot-reload/duplicate-module issues creating two storage instances that both bind the same domain object; dependency-injection wiring that passes a cached domain into several storages.

Related errors


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