{"record":{"id":"7c0bc7b5a6102c76","repo":"windmill-labs/windmill","slug":"step-with-id-stepid-not-found-in-flow-availa","errorCode":null,"errorMessage":"Step with id \"${stepId}\" not found in flow. Available steps: ${getAvailableFlowStepIds(flowValue)}","messagePattern":"Step with id \"(.+?)\" not found in flow\\. Available steps: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/shared.ts","lineNumber":1904,"sourceCode":"\tflowValue,\n\tstepId,\n\targs,\n\tworkspace,\n\ttoolCallbacks,\n\ttoolId,\n\tbackground,\n\tdetachAfterMs,\n\tloadScript = loadDeployedScriptForFlowStep,\n\tloadFlowPreviewValue\n}: FlowStepTestRunConfig): Promise<string> {\n\tconst targetModule = findModuleInFlow(flowValue, stepId) ?? undefined\n\n\tif (!targetModule) {\n\t\ttoolCallbacks.setToolStatus(toolId, {\n\t\t\tcontent: `Step \"${stepId}\" not found in flow`,\n\t\t\terror: `Step with id \"${stepId}\" does not exist in the current flow`\n\t\t})\n\t\tthrow new Error(\n\t\t\t`Step with id \"${stepId}\" not found in flow. Available steps: ${getAvailableFlowStepIds(flowValue)}`\n\t\t)\n\t}\n\n\tconst moduleValue = targetModule.value\n\tconst stepArgs = normalizeFlowStepArgs(args)\n\n\tif (moduleValue.type === 'rawscript') {\n\t\treturn executeTestRun({\n\t\t\tjobStarter: () =>\n\t\t\t\tJobService.runScriptPreview({\n\t\t\t\t\tworkspace,\n\t\t\t\t\trequestBody: {\n\t\t\t\t\t\tcontent: moduleValue.content ?? '',\n\t\t\t\t\t\tlanguage: moduleValue.language,\n\t\t\t\t\t\targs: flowStepArgsForModule(targetModule.id, stepArgs)\n\t\t\t\t\t}\n\t\t\t\t}),","sourceCodeStart":1886,"sourceCodeEnd":1922,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/shared.ts#L1886-L1922","documentation":"Flow step tools (e.g. editing or testing a specific step) resolve the requested stepId within the current flow value. When no module with that id exists, the tool throws an error listing the ids that DO exist via getAvailableFlowStepIds, so the model can pick a valid one. A tool status with 'Step \"X\" not found in flow' is also recorded.","triggerScenarios":"The model called a step-targeted tool with a step id that does not exist in the loaded flow — typically a hallucinated/renamed id, an id from a different flow version, or an empty/failed flow load leaving flowValue without the expected modules.","commonSituations":"The flow was edited (step deleted or id regenerated) after the model read it; the model invented an id like 'step_1' instead of using the real ids; the chat context holds a stale flow JSON; user pasted a step name instead of its id.","solutions":["Retry the tool call using one of the ids printed in 'Available steps: [...]' (also visible via getFlowStepIds from the current flow value).","Re-read the current flow JSON (update_flow_value / fresh flow load) to refresh step ids, then target the correct one.","If the step was deleted, recreate it or ask the model to add a new step instead of editing the missing one.","Confirm the chat is operating on the intended flow — a stale context may not contain the step you mean."],"exampleFix":"// before\n{\"name\": \"test_flow_step\", \"arguments\": {\"step_id\": \"step_1\"}} // not found\n// after\n{\"name\": \"test_flow_step\", \"arguments\": {\"step_id\": \"a1b2c3\"}} // id from Available steps list","handlingStrategy":"validation","validationCode":"const stepIds = (flowValue?.modules?.roots ?? []).map((m) => m?.value?.id).filter(Boolean)\nif (!stepIds.includes(stepId)) {\n  throw new Error(`step_id must be one of: ${stepIds.join(', ')}`) // fail fast with valid options\n}","typeGuard":"function isValidStepId(flowValue: { modules?: { roots?: Array<{ value?: { id?: string } }> } } | null, stepId: string): boolean {\n  return !!flowValue?.modules?.roots?.some((m) => m?.value?.id === stepId)\n}","tryCatchPattern":"try {\n  await testFlowStep({ stepId, ... })\n} catch (e) {\n  const m = e.message.match(/Available steps: \\[(.*)\\]/)\n  if (m) {\n    const validIds = m[1].split(', ').map((s) => s.replace(/\"/g, ''))\n    // retry with a valid id, or surface the list to the user\n  }\n}","preventionTips":["Read step ids from the live flow value immediately before calling step tools, never from memory.","Refresh flow context after any structural edit (add/delete/rename of steps).","Parse the 'Available steps' list from the error to self-correct model tool calls.","Distinguish step ids from step summaries/names — only ids are valid targets."],"tags":["copilot","flow-steps","lookup-failure"],"backgroundTag":"resource-not-found","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}