{"record":{"id":"490c5fff88335026","repo":"mastra-ai/mastra","slug":"mastrafactory-duplicate-integration-id-integra","errorCode":null,"errorMessage":"MastraFactory: duplicate integration id '${integration.id}' in 'integrations'.","messagePattern":"MastraFactory: duplicate integration id '(.+?)' in 'integrations'\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/factory.ts","lineNumber":355,"sourceCode":"\n    // Explicit integrations win. Platform credentials fill only missing GitHub\n    // and Linear slots so callers can override either provider independently.\n    const integrations = [...(this.#config.integrations ?? [])];\n    if (hasPlatformCredentials()) {\n      if (!integrations.some(integration => integration.id === 'github')) {\n        integrations.push(new PlatformGithubIntegration({ slug: this.#config.platform?.githubAppSlug }));\n      }\n      if (!integrations.some(integration => integration.id === 'linear')) {\n        integrations.push(new PlatformLinearIntegration());\n      }\n    }\n\n    // Validate ids up front so a copy-paste duplicate fails loud instead of one\n    // instance silently shadowing the other.\n    const integrationIds = new Set<string>();\n    for (const integration of integrations) {\n      if (integrationIds.has(integration.id)) {\n        throw new Error(`MastraFactory: duplicate integration id '${integration.id}' in 'integrations'.`);\n      }\n      integrationIds.add(integration.id);\n    }\n    const rules = this.#config.rules ?? builtInFactoryRules();\n    assertFactoryRules(rules);\n\n    // FactoryStorage owns every app-table domain and initializes them through\n    // the same lifecycle as the backend connection.\n    const intakeStorage = storage.registerDomain(new IntakeStorage());\n    const auditStorage = storage.registerDomain(new AuditStorage());\n    const workItemsStorage = storage.registerDomain(new WorkItemsStorage());\n    const modelCredentialsStorage = storage.registerDomain(new ModelCredentialsStorage(secretEncryption));\n    const modelPacksStorage = storage.registerDomain(new ModelPacksStorage());\n    const memorySettingsStorage = storage.registerDomain(new MemorySettingsStorage());\n    const customProvidersStorage = storage.registerDomain(new CustomProvidersStorage(secretEncryption));\n    const queueHealthStorage = storage.registerDomain(new QueueHealthStorage());\n    // Generic integration storage (connections/subscriptions/settings) — the\n    // default persistence surface for integrations without a bespoke domain.","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/factory.ts#L337-L373","documentation":"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.","triggerScenarios":"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]).","commonSituations":"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.","solutions":["Deduplicate the integrations array before constructing the factory (e.g. filter by id or use a Map keyed by id).","Give each integration instance a unique id when registering it.","Check for accidental double-spreading of the integrations array in the config.","Log or assert the list of ids in your config builder to catch duplicates early in tests."],"exampleFix":"// before\nintegrations: [githubIntegration, githubIntegration]\n\n// after\nintegrations: [githubIntegration, slackIntegration] // unique ids","handlingStrategy":"validation","validationCode":"function assertUniqueIntegrationIds(integrations) {\n  const ids = integrations.map(i => i.id);\n  const dupes = ids.filter((id, i) => ids.indexOf(id) !== i);\n  if (dupes.length) throw new Error(`Duplicate integration ids: ${dupes.join(', ')}`);\n}\nassertUniqueIntegrationIds(factoryConfig.integrations ?? []);","typeGuard":"function hasUniqueIds(integrations) {\n  return Array.isArray(integrations) && new Set(integrations.map(i => i.id)).size === integrations.length;\n}","tryCatchPattern":"try {\n  const factory = new MastraFactory(config);\n  await factory.prepare();\n} catch (err) {\n  if (err.message.includes('duplicate integration id')) {\n    const id = err.message.match(/'([^']+)'/)?.[1];\n    throw new Error(`Fix config: integration '${id}' registered more than once`, { cause: err });\n  }\n  throw err;\n}","preventionTips":["Build the integrations array from a single source of truth (a registry module), not inline literals","Deduplicate by id when merging integration lists from multiple sources","Add a test asserting hasUniqueIds on the production config","Avoid copy-pasting integration registrations without changing ids"],"tags":["configuration","duplicate","integration","validation"],"backgroundTag":"duplicate-identifier","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}