{"record":{"id":"ca6510e31fc18cf8","repo":"mastra-ai/mastra","slug":"dynamic-workflow-references-step-id-which-is","errorCode":null,"errorMessage":"Dynamic workflow references step \"${id}\" which is not registered as an agent or tool on this Mastra instance.","messagePattern":"Dynamic workflow references step \"(.+?)\" which is not registered as an agent or tool on this Mastra instance\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/workflows/dynamic/rehydrate.ts","lineNumber":294,"sourceCode":"          `Dynamic workflow references tool \"${entry.toolId}\" which is not registered on this Mastra instance.`,\n        );\n      }\n      return { type: 'tool', id: entry.id, toolId: entry.toolId, tool, options: rebuildToolOptions(entry) };\n    }\n    case 'step': {\n      const { id } = entry.step;\n      // Wrap the resolved agent/tool in a real Step (same adapters `createStep`\n      // uses) so the entry honors the executeStep contract instead of casting a\n      // raw Agent/Tool instance — those don't carry a step-shaped `execute`.\n      const agent = tryGetAgentById(mastra, id);\n      if (agent) {\n        return { type: 'step', step: createStepFromAgent(agent) as unknown as Step };\n      }\n      const tool = tryGetToolById(mastra, id);\n      if (tool) {\n        return { type: 'step', step: createStepFromTool(tool as any) as unknown as Step };\n      }\n      throw new Error(\n        `Dynamic workflow references step \"${id}\" which is not registered as an agent or tool on this Mastra instance.`,\n      );\n    }\n    case 'workflow': {\n      const nested = assertWorkflowExists(mastra, entry.workflowId);\n      // Same call-site identity rule as top-level nested workflows: run the\n      // clone under the declared id so results are keyed the way the portable\n      // definition addresses them.\n      const step = entry.id && entry.id !== nested.id ? cloneWorkflow(nested as any, { id: entry.id }) : nested;\n      return { type: 'step', step: step as unknown as Step };\n    }\n    case 'mapping':\n      throw new Error(\n        `mapping entries cannot appear inside .parallel(), .branch(), or .foreach(); they must be top-level.`,\n      );\n  }\n}\n","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workflows/dynamic/rehydrate.ts#L276-L312","documentation":"A 'step' entry in a stored dynamic workflow resolves its id first as an agent, then as a tool, via `createStepFromAgent`/`createStepFromTool`. If the id matches neither, the library throws because stored plain-id step entries can only be backed by registered agents or tools.","triggerScenarios":"rehydrateWorkflow processes a stored step entry whose id (entry.id or nested id) is not registered as an agent or tool on the Mastra instance — e.g. referencing a plain Step object that was never registered, or an id typo.","commonSituations":"Assuming arbitrary inline `createStep()` steps can be referenced by id in stored graphs (they must be serialized inline or registered); typos in step ids; renaming agents/tools without updating stored graphs.","solutions":["Register the referenced resource as an agent or tool on the Mastra instance so the id resolves.","If the step is a plain Step, re-serialize the workflow so the step is embedded inline rather than referenced by id.","Fix id mismatches between the stored graph and the registry (typo/rename).","Pre-validate each stored step id with `mastra.getAgent(id) ?? mastra.getTool(id)` before rehydrating."],"exampleFix":"// before: stored { type: 'step', id: 'myStep' } with only a local createStep()\n// after: register it as a tool-backed step\nconst mastra = new Mastra({ tools: { myStep: createToolFromStep(myStep) } });","handlingStrategy":"validation","validationCode":"function assertStepIdsResolvable(stored, mastra) {\n  for (const e of stored.entries) {\n    if (e.type === 'step') {\n      const id = typeof e === 'string' ? e : e.id;\n      if (id && !mastra.getAgent?.(id) && !mastra.getTool?.(id)) {\n        throw new Error(`Step id \"${id}\" resolves to neither agent nor tool`);\n      }\n    }\n  }\n}","typeGuard":"function stepIdResolves(mastra: Mastra, id: string): boolean {\n  return !!mastra.getAgent?.(id) || !!mastra.getTool?.(id);\n}","tryCatchPattern":"try {\n  const wf = rehydrateWorkflow(stored, mastra);\n} catch (err) {\n  const m = err instanceof Error && err.message.match(/references step \"([^\"]+)\" which is not registered/);\n  if (m) throw new Error(`'${m[1]}' must be registered as an agent or tool (plain steps cannot be referenced by id).`);\n  throw err;\n}","preventionTips":["Only reference agents/tools by id in stored graphs; embed plain steps inline instead.","Avoid id collisions between agents and tools when a step id must resolve.","Pre-validate all step ids against the registry before rehydration."],"tags":["workflow","step","registration","rehydration"],"backgroundTag":"unregistered-resource-reference","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}