medusajs/medusa · error · Error
step workflow not found: ${data.workflowId} for step ${data.
Error message
step workflow not found: ${data.workflowId} for step ${data.id} What it means
Dev-server error from StepHandler.resolveSourcePath: the step registered with only a workflowId, and the inverse registry has no entry for `workflow:<workflowId>` — meaning that workflow has not been registered with the dev server (or was registered under a different id). Without it the step's source file cannot be located for hot-reload.
Source
Thrown at packages/core/utils/src/dev-server/handlers/step-handler.ts:32
if (!data.sourcePath && !data.workflowId) {
throw new Error(
`Step registration requires either sourcePath or workflowId. Received: ${JSON.stringify(
data
)}`
)
}
}
resolveSourcePath(data: StepResourceData): string {
if (data.sourcePath) {
return data.sourcePath
}
// Look up workflow's source path
const workflowKey = `workflow:${data.workflowId}`
const workflowSourcePaths = this.inverseRegistry.get(workflowKey)
if (!workflowSourcePaths || workflowSourcePaths.length === 0) {
throw new Error(
`step workflow not found: ${data.workflowId} for step ${data.id}`
)
}
return workflowSourcePaths[0]
}
createEntry(data: StepResourceData): ResourceEntry {
return {
id: data.id,
workflowId: data.workflowId,
}
}
getInverseKey(data: StepResourceData): string {
return `${this.type}:${data.id}`View on GitHub (pinned to 5e06e544a2)
Solutions
- Register the workflow resource (type 'workflow' with matching id and its sourcePath) before registering its steps.
- Verify the workflowId string exactly matches the workflow's registered id.
- Alternatively, register the step with its own sourcePath to avoid depending on workflow registration order.
Example fix
// before
registerDevServerResource({ type: 'step', id: 's1', workflowId: 'cart-workflow' })
// 'cart-workflow' never registered
// after
registerDevServerResource({ type: 'workflow', id: 'cart-workflow', sourcePath: wfPath })
registerDevServerResource({ type: 'step', id: 's1', workflowId: 'cart-workflow' }) Defensive patterns
Strategy: validation
Validate before calling
if (!data.sourcePath) {
const wf = inverseRegistry.get(`workflow:${data.workflowId}`)
if (!wf?.length) throw new Error(`Register workflow ${data.workflowId} before its steps`)
} Prevention
- Register workflows before their steps in loader ordering.
- Use the exact workflow id string from createWorkflow in step registration.
- Give steps their own sourcePath to decouple from workflow registration order.
When it happens
Trigger: Registering a step with workflowId: 'my-workflow' before (or without ever) registering a workflow resource whose id is 'my-workflow'; using the workflow's function name instead of its registered id string.
Common situations: Ordering issues in custom loaders where steps load before workflows; renaming a workflow without updating the workflowId referenced by step registrations; registering only part of a project's resources during incremental setup.
Related errors
- Step registration requires id. Received: ${JSON.stringify(da
- Step registration requires either sourcePath or workflowId.
- Workflow registration requires sourcePath. Received: ${JSON.
- Workflow registration requires id. Received: ${JSON.stringif
- Job registration requires id. Received: ${JSON.stringify(dat
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/fd73659113e1f5c8.
Report an issue: GitHub.