medusajs/medusa · error · MedusaError
invalid_data
invalid_data
Error message
Sales channels with IDs ${notFound.join(", ")} do not exist What it means
cancel() in the Redis engine resolves the flow definition via MedusaWorkflow.getWorkflow before loading the transaction. An unregistered workflow id yields MedusaError NOT_FOUND with the id embedded in the message.
Source
Thrown at packages/core/core-flows/src/api-key/steps/validate-sales-channel-exists.ts:40
* If the sales channel does not exist, the step throws an error.
*/
export const validateSalesChannelsExistStep = createStep(
validateSalesChannelsExistStepId,
async (data: ValidateSalesChannelsExistStepInput, { container }) => {
const salesChannelModuleService =
container.resolve<ISalesChannelModuleService>(Modules.SALES_CHANNEL)
const salesChannels = await salesChannelModuleService.listSalesChannels(
{ id: data.sales_channel_ids },
{ select: ["id"] }
)
const salesChannelIds = salesChannels.map((v) => v.id)
const notFound = arrayDifference(data.sales_channel_ids, salesChannelIds)
if (notFound.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Sales channels with IDs ${notFound.join(", ")} do not exist`
)
}
return new StepResponse(salesChannelIds)
}
)
View on GitHub (pinned to 5e06e544a2)
Solutions
- Import the workflow module in the cancelling process, or route cancels through a service that has it registered
- Verify the id matches the createWorkflow id exactly
- Handle NOT_FOUND gracefully for stale cancellations
Example fix
// before
await engine.cancel(row.workflow_id, row.transaction_id)
// after
if (!MedusaWorkflow.getWorkflow(row.workflow_id)) return { alreadyGone: true }
await engine.cancel(row.workflow_id, row.transaction_id) Defensive patterns
Strategy: type-guard
Validate before calling
if (!MedusaWorkflow.getWorkflow(workflowId)) throw new Error(`cannot cancel unregistered workflow ${workflowId}`)
await engine.cancel(workflowId, transactionId) Type guard
const isRegistered = (id: string) => Boolean(MedusaWorkflow.getWorkflow(id))
Try / catch
catch (e) { if (e.type === 'not_found' && e.message.includes('not found')) return { status: 'unknown-workflow' }; throw e } Prevention
- Import workflow definitions in monitoring/admin processes
- Treat unknown workflow cancels as no-ops for idempotency
When it happens
Trigger: cancel('typo-id', txId) or cancelling a workflow whose defining module is not imported in the process handling the cancel request.
Common situations: Admin/monitoring services that cancel arbitrary workflows by id read from a database but never import the workflow modules; deployments splitting the API and engine processes.
Related errors
- --config file must be of type .json or .yaml - ${configFileC
- invalid_data
- Key ${key} already exists in app metadata
- --paths must be a directory - ${additionalPath}
- --base must be a file - ${baseFile}
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/376536e82116b612.
Report an issue: GitHub.