{"record":{"id":"871b5aee0f2d5d2a","repo":"mastra-ai/mastra","slug":"runid-required-to-cancel-workflow-run","errorCode":null,"errorMessage":"runId required to cancel workflow run","messagePattern":"runId required to cancel workflow run","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"packages/server/src/server/handlers/workflows.ts","lineNumber":1308,"sourceCode":"  method: 'POST',\n  path: '/workflows/:workflowId/runs/:runId/cancel',\n  responseType: 'json',\n  pathParamSchema: workflowRunPathParams,\n  responseSchema: workflowControlResponseSchema,\n  summary: 'Cancel workflow run',\n  description: 'Cancels an in-progress workflow execution',\n  tags: ['Workflows'],\n  requiresAuth: true,\n  handler: async ({ mastra, workflowId, runId, requestContext }) => {\n    try {\n      const effectiveResourceId = getEffectiveResourceId(requestContext, undefined);\n\n      if (!workflowId) {\n        throw new HTTPException(400, { message: 'Workflow ID is required' });\n      }\n\n      if (!runId) {\n        throw new HTTPException(400, { message: 'runId required to cancel workflow run' });\n      }\n\n      const { workflow } = await listWorkflowsFromSystem({ mastra, workflowId });\n\n      if (!workflow) {\n        throw new HTTPException(404, { message: 'Workflow not found' });\n      }\n\n      const run = await workflow.getWorkflowRunById(runId);\n\n      if (!run) {\n        throw new HTTPException(404, { message: 'Workflow run not found' });\n      }\n\n      await validateRunOwnership(run, effectiveResourceId);\n\n      const _run = await workflow.createRun({ runId, resourceId: run.resourceId });\n","sourceCodeStart":1290,"sourceCodeEnd":1326,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/handlers/workflows.ts#L1290-L1326","documentation":"This 400 error is thrown by the cancel-workflow-run handler when the request provides a workflowId but omits `runId`. Canceling a run requires knowing which specific run execution to cancel; without runId the handler cannot proceed and rejects with 400.","triggerScenarios":"Calling the cancel workflow run endpoint without the runId path/body parameter, e.g. POST /api/workflows/:workflowId/cancel with no run identifier.","commonSituations":"Frontend cancel button wired before the run has been started (runId not yet captured from the start response); confusing the workflowId with the runId; older API shape where runId was embedded differently.","solutions":["Include the runId of the run to cancel in the request (path parameter per the route definition).","Capture the runId from the workflow start/startAsync response and store it for later cancellation.","If no runId exists, the run may have already finished — list runs to confirm a cancellable (running) run first.","Verify the correct cancel endpoint/route is being used for the installed @mastra/core version."],"exampleFix":"// before\nawait client.getWorkflow('orderProcessing').cancelRun();\n// after\nawait client.getWorkflow('orderProcessing').cancelRun(runId);","handlingStrategy":"validation","validationCode":"if (!runId) throw new Error('cancelRun requires the runId returned when the run was started');","typeGuard":"function hasRunId(p: { runId?: string }): p is { runId: string } {\n  return typeof p.runId === 'string' && p.runId.length > 0;\n}","tryCatchPattern":"try {\n  await client.getWorkflow(workflowId).cancelRun(runId);\n} catch (e) {\n  if (e?.status === 400 && /runId required to cancel/.test(e?.message ?? '')) {\n    throw new Error('Capture runId from the start() response and pass it to cancelRun');\n  }\n  throw e;\n}","preventionTips":["Persist the runId from start()/startAsync for later cancel calls.","Disable cancel UI until a runId exists in state.","Check whether the run already finished — finished runs may not need cancellation.","Match the route parameter names of the installed server version."],"tags":["http-400","validation","workflow","missing-parameter"],"backgroundTag":"missing-required-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}