{"record":{"id":"376536e82116b612","repo":"medusajs/medusa","slug":"invalid-data","errorCode":"invalid_data","errorMessage":"Sales channels with IDs ${notFound.join(\", \")} do not exist","messagePattern":"Sales channels with IDs (.+?) do not exist","errorType":"validation","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/core/core-flows/src/api-key/steps/validate-sales-channel-exists.ts","lineNumber":40,"sourceCode":" * If the sales channel does not exist, the step throws an error.\n */\nexport const validateSalesChannelsExistStep = createStep(\n  validateSalesChannelsExistStepId,\n  async (data: ValidateSalesChannelsExistStepInput, { container }) => {\n    const salesChannelModuleService =\n      container.resolve<ISalesChannelModuleService>(Modules.SALES_CHANNEL)\n\n    const salesChannels = await salesChannelModuleService.listSalesChannels(\n      { id: data.sales_channel_ids },\n      { select: [\"id\"] }\n    )\n\n    const salesChannelIds = salesChannels.map((v) => v.id)\n\n    const notFound = arrayDifference(data.sales_channel_ids, salesChannelIds)\n\n    if (notFound.length) {\n      throw new MedusaError(\n        MedusaError.Types.INVALID_DATA,\n        `Sales channels with IDs ${notFound.join(\", \")} do not exist`\n      )\n    }\n\n    return new StepResponse(salesChannelIds)\n  }\n)\n","sourceCodeStart":22,"sourceCodeEnd":49,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/core/core-flows/src/api-key/steps/validate-sales-channel-exists.ts#L22-L49","documentation":"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.","triggerScenarios":"cancel('typo-id', txId) or cancelling a workflow whose defining module is not imported in the process handling the cancel request.","commonSituations":"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.","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"],"exampleFix":"// before\nawait engine.cancel(row.workflow_id, row.transaction_id)\n// after\nif (!MedusaWorkflow.getWorkflow(row.workflow_id)) return { alreadyGone: true }\nawait engine.cancel(row.workflow_id, row.transaction_id)","handlingStrategy":"type-guard","validationCode":"if (!MedusaWorkflow.getWorkflow(workflowId)) throw new Error(`cannot cancel unregistered workflow ${workflowId}`)\nawait engine.cancel(workflowId, transactionId)","typeGuard":"const isRegistered = (id: string) => Boolean(MedusaWorkflow.getWorkflow(id))","tryCatchPattern":"catch (e) { if (e.type === 'not_found' && e.message.includes('not found')) return { status: 'unknown-workflow' }; throw e }","preventionTips":["Import workflow definitions in monitoring/admin processes","Treat unknown workflow cancels as no-ops for idempotency"],"tags":["workflow-engine","redis","workflow-registry","not-found"],"backgroundTag":"workflow-not-registered","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}