{"record":{"id":"8b4c83d26cf78725","repo":"mastra-ai/mastra","slug":"sync-function-name-already-registered","errorCode":null,"errorMessage":"Sync function \"${name}\" already registered","messagePattern":"Sync function \"(.+?)\" already registered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/integration/integration.ts","lineNumber":18,"sourceCode":"import type { ToolAction } from '../tools';\nimport type { Workflow } from '../workflows';\n\nexport class Integration<ToolsParams = void, ApiClient = void> {\n  name: string = 'Integration';\n  private workflows: Record<string, Workflow>;\n\n  constructor() {\n    this.workflows = {};\n  }\n\n  /**\n   * Workflows\n   */\n\n  registerWorkflow(name: string, fn: Workflow) {\n    if (this.workflows[name]) {\n      throw new Error(`Sync function \"${name}\" already registered`);\n    }\n    this.workflows[name] = fn;\n  }\n\n  public listWorkflows({ serialized }: { serialized?: boolean }): Record<string, Workflow> {\n    if (serialized) {\n      return Object.entries(this.workflows).reduce((acc, [k, v]) => {\n        return {\n          ...acc,\n          [k]: {\n            name: v.name,\n          },\n        };\n      }, {});\n    }\n    return this.workflows;\n  }\n","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/integration/integration.ts#L1-L36","documentation":"MastraIntegration.registerWorkflow stores workflows in a plain name-keyed map and treats duplicate registration as a programming error. If a workflow with the same name already exists in this.#workflows, it throws instead of overwriting, preventing accidental replacement of a registered workflow.","triggerScenarios":"Calling integration.registerWorkflow(name, fn) twice with the same name — e.g. re-registering during hot module reload (HMR), double module import, or registering the same workflow instance under a conflicting key.","commonSituations":"Dev-server hot reload re-running registration code; two files both registering a workflow named 'deploy'; a factory function invoked more than once; copy-pasted registration blocks with the same name.","solutions":["Register each workflow only once — move registration to module top-level or a run-once init function","Give duplicate registrations unique names, or check existing names via listWorkflows() first","Use this.workflows[name] ?? this.registerWorkflow(...) semantics yourself, or add an idempotency guard in your registration code","If caused by HMR, clear registrations on module dispose or use a guard keyed on module state"],"exampleFix":"// before\nintegration.registerWorkflow('deploy', deployWorkflow);\nintegration.registerWorkflow('deploy', deployWorkflowV2); // throws\n// after\nif (!Object.keys(integration.listWorkflows({})).includes('deploy')) {\n  integration.registerWorkflow('deploy', deployWorkflow);\n}","handlingStrategy":"validation","validationCode":"if (Object.keys(integration.listWorkflows({})).includes(name)) {\n  throw new Error(`Workflow \"${name}\" is already registered`);\n}","typeGuard":"function isWorkflowRegistered(integration, name) {\n  return Object.prototype.hasOwnProperty.call(integration.listWorkflows({}), name);\n}","tryCatchPattern":"try {\n  integration.registerWorkflow(name, workflow);\n} catch (e) {\n  if (e.message.includes('already registered')) {\n    // idempotent registration — safe to ignore or log\n  } else {\n    throw e;\n  }\n}","preventionTips":["Keep workflow registration in a single module/init function","Use unique, namespaced workflow names","Add run-once guards for HMR/dev-server double execution","Before registering, check listWorkflows() for name collisions"],"tags":["registration","duplicate","workflow","integration"],"backgroundTag":"duplicate-registration","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}