{"record":{"id":"3050c4ac05d72806","repo":"Mintplex-Labs/anything-llm","slug":"unknown-flow-type-step-type","errorCode":null,"errorMessage":"Unknown flow type: ${step.type}","messagePattern":"Unknown flow type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/agentFlows/executor.js","lineNumber":168,"sourceCode":"          config.variables.forEach((v) => {\n            if (v.name && !this.variables[v.name]) {\n              this.variables[v.name] = v.value || \"\";\n            }\n          });\n        }\n        result = this.variables;\n        break;\n      case FLOW_TYPES.API_CALL.type:\n        result = await executeApiCall(config, context);\n        break;\n      case FLOW_TYPES.LLM_INSTRUCTION.type:\n        result = await executeLLMInstruction(config, context);\n        break;\n      case FLOW_TYPES.WEB_SCRAPING.type:\n        result = await executeWebScraping(config, context);\n        break;\n      default:\n        throw new Error(`Unknown flow type: ${step.type}`);\n    }\n\n    // Store result in variable if specified\n    if (config.resultVariable || config.responseVariable) {\n      const varName = config.resultVariable || config.responseVariable;\n      this.variables[varName] = result;\n    }\n\n    // If directOutput is true, mark this result for direct output\n    if (config.directOutput) result = { directOutput: true, result };\n    return result;\n  }\n\n  /**\n   * Execute entire flow\n   * @param {Object} flow - The flow to execute\n   * @param {Object} initialVariables - Initial variables for the flow\n   * @param {Object} aibitat - The aibitat instance from the agent handler","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/agentFlows/executor.js#L150-L186","documentation":"Thrown by FlowExecutor.executeStep() when a flow step's `type` does not match any case in its switch (start, apiCall, llmInstruction, webScraping). The executor only knows the four FLOW_TYPES it imports from flowTypes.js. This protects against executing a block the runtime cannot handle. Note that AgentFlows.saveFlow() (error 387) validates this at save time, so reaching this throw means the flow file was written bypassing saveFlow (hand-edited, migrated, or created by a newer build).","triggerScenarios":"Calling FlowExecutor.executeStep() with a step object whose `.type` is a string other than \"start\", \"apiCall\", \"llmInstruction\", or \"webScraping\". This includes a step.type of undefined (missing field), a renamed type, or a future type such as a code-execution or file-writing block that this build does not register.","commonSituations":"A flow JSON edited directly on disk in storage/plugins/agent-flows; a flow exported from a newer AnythingLLM version containing block types the older executor does not recognize; a corrupt/partially-written flow file where step.type is missing.","solutions":["Inspect the offending flow JSON under STORAGE_DIR/plugins/agent-flows and find the step whose `type` is not start/apiCall/llmInstruction/webScraping.","Remove or replace the unsupported step, then re-save the flow through the UI so saveFlow() re-validates all step types.","If the block type is valid for your setup, upgrade AnythingLLM to a version whose executor.js handles that type.","If migrating between platforms (Desktop to Docker), recreate the flow on the target platform instead of copying the JSON."],"exampleFix":"// before - flow JSON contains an unknown block\n{\"steps\":[{\"type\":\"codeExecution\",\"config\":{...}}]}\n// after - remove the unsupported step or replace with a supported type\n{\"steps\":[{\"type\":\"llmInstruction\",\"config\":{\"instruction\":\"...\"}}]}","handlingStrategy":"validation","validationCode":"const { FLOW_TYPES } = require(\"./flowTypes\");\nconst SUPPORTED = Object.values(FLOW_TYPES).map((d) => d.type);\nfunction validateFlowSteps(flow) {\n  const bad = (flow.config.steps || []).filter(\n    (s) => !SUPPORTED.includes(s.type)\n  );\n  if (bad.length) throw new Error(`Unsupported step types: ${bad.map((s) => s.type).join(\", \")}`);\n}","typeGuard":"const SUPPORTED_TYPES = new Set(Object.values(FLOW_TYPES).map((d) => d.type));\nconst isSupportedStep = (step) =>\n  step && typeof step.type === \"string\" && SUPPORTED_TYPES.has(step.type);","tryCatchPattern":"try {\n  await executor.executeStep(step);\n} catch (e) {\n  if (e.message.startsWith(\"Unknown flow type\")) {\n    // skip or log the unsupported step rather than aborting the whole flow\n  } else throw e;\n}","preventionTips":["Always create/save flows through AgentFlows.saveFlow so step types are validated against FLOW_TYPES.","Never hand-edit flow JSON under storage/plugins/agent-flows; if you do, run validateFlowSteps before executing.","When importing flows across versions/editions, re-save them on the target platform to re-trigger validation."],"tags":["agent-flows","flow-execution","validation","switch-default"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}