mastra-ai/mastra · error

MastraFactory: duplicate integration id '${integration.id}'

Error message

MastraFactory: duplicate integration id '${integration.id}' in 'integrations'.

What it means

During prepare(), the factory validates that every integration id in config.integrations is unique before building the registrations. Duplicate ids would cause one integration instance to silently shadow the other in lookups and tool registries, so the factory fails loud with the offending id instead. The check runs up front, before rules validation and any side effects.

Source

Thrown at mastracode/factory/src/factory.ts:355

    // Explicit integrations win. Platform credentials fill only missing GitHub
    // and Linear slots so callers can override either provider independently.
    const integrations = [...(this.#config.integrations ?? [])];
    if (hasPlatformCredentials()) {
      if (!integrations.some(integration => integration.id === 'github')) {
        integrations.push(new PlatformGithubIntegration({ slug: this.#config.platform?.githubAppSlug }));
      }
      if (!integrations.some(integration => integration.id === 'linear')) {
        integrations.push(new PlatformLinearIntegration());
      }
    }

    // Validate ids up front so a copy-paste duplicate fails loud instead of one
    // instance silently shadowing the other.
    const integrationIds = new Set<string>();
    for (const integration of integrations) {
      if (integrationIds.has(integration.id)) {
        throw new Error(`MastraFactory: duplicate integration id '${integration.id}' in 'integrations'.`);
      }
      integrationIds.add(integration.id);
    }
    const rules = this.#config.rules ?? builtInFactoryRules();
    assertFactoryRules(rules);

    // FactoryStorage owns every app-table domain and initializes them through
    // the same lifecycle as the backend connection.
    const intakeStorage = storage.registerDomain(new IntakeStorage());
    const auditStorage = storage.registerDomain(new AuditStorage());
    const workItemsStorage = storage.registerDomain(new WorkItemsStorage());
    const modelCredentialsStorage = storage.registerDomain(new ModelCredentialsStorage(secretEncryption));
    const modelPacksStorage = storage.registerDomain(new ModelPacksStorage());
    const memorySettingsStorage = storage.registerDomain(new MemorySettingsStorage());
    const customProvidersStorage = storage.registerDomain(new CustomProvidersStorage(secretEncryption));
    const queueHealthStorage = storage.registerDomain(new QueueHealthStorage());
    // Generic integration storage (connections/subscriptions/settings) — the
    // default persistence surface for integrations without a bespoke domain.

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Deduplicate the integrations array before constructing the factory (e.g. filter by id or use a Map keyed by id).
  2. Give each integration instance a unique id when registering it.
  3. Check for accidental double-spreading of the integrations array in the config.
  4. Log or assert the list of ids in your config builder to catch duplicates early in tests.

Example fix

// before
integrations: [githubIntegration, githubIntegration]

// after
integrations: [githubIntegration, slackIntegration] // unique ids
Defensive patterns

Strategy: validation

Validate before calling

function assertUniqueIntegrationIds(integrations) {
  const ids = integrations.map(i => i.id);
  const dupes = ids.filter((id, i) => ids.indexOf(id) !== i);
  if (dupes.length) throw new Error(`Duplicate integration ids: ${dupes.join(', ')}`);
}
assertUniqueIntegrationIds(factoryConfig.integrations ?? []);

Type guard

function hasUniqueIds(integrations) {
  return Array.isArray(integrations) && new Set(integrations.map(i => i.id)).size === integrations.length;
}

Try / catch

try {
  const factory = new MastraFactory(config);
  await factory.prepare();
} catch (err) {
  if (err.message.includes('duplicate integration id')) {
    const id = err.message.match(/'([^']+)'/)?.[1];
    throw new Error(`Fix config: integration '${id}' registered more than once`, { cause: err });
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing two integration instances with the same integration.id in the integrations array of the factory config — typically from a copy-pasted registration or pushing the same integration object/array element twice (e.g. [...integrations, githubIntegration, githubIntegration]).

Common situations: Copy-pasting an integration registration and forgetting to change its id; accidentally spreading an integrations array twice; constructing two instances of the same integration class that share a static default id.

Related errors


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