{"record":{"id":"d89485c21ae2815c","repo":"Budibase/budibase","slug":"cannot-render-an-empty-flow-chain","errorCode":null,"errorMessage":"Cannot render an empty flow chain","messagePattern":"Cannot render an empty flow chain","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowCanvas/renderers/FlowChainRenderer.ts","lineNumber":105,"sourceCode":"const renderBlock = (step: AutomationBlock, context: ChainRenderContext) => {\n  if (step.stepId === AutomationActionStepId.BRANCH) {\n    renderBranchSplit(step, context)\n    return false\n  }\n\n  if (isLoopV2Step(step)) {\n    renderLoop(step, context)\n    return true\n  }\n\n  renderStep(step, context)\n  return true\n}\n\nconst getRenderResult = (context: ChainRenderContext): ChainRenderResult => {\n  const lastSource = getLastSource(context)\n  if (!lastSource) {\n    throw new Error(\"Cannot render an empty flow chain\")\n  }\n\n  return {\n    lastNodeId: lastSource.nodeId,\n    lastNodeBlock: lastSource.block,\n    bottomY: context.currentY,\n    branched: context.branched,\n    terminals: context.terminals,\n  }\n}\n\nexport const renderChain = (\n  chain: AutomationBlock[],\n  parentNodeId: string,\n  parentBlock: FlowBlockContext,\n  startY: number,\n  deps: GraphBuildDeps\n): ChainRenderResult => {","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/builder/src/components/automation/AutomationBuilder/FlowChart/FlowCanvas/renderers/FlowChainRenderer.ts#L87-L123","documentation":"The FlowChart's render pipeline (getRenderResult, invoked by renderChain) computes layout for a chain of automation flow nodes and needs at least one node's source to anchor the rendering. When getLastSource returns undefined — meaning the chain context has no nodes — rendering cannot proceed and this error is thrown.","triggerScenarios":"renderChain called with a ChainRenderContext whose node list is empty — e.g. an automation with zero steps, a branch that filtered out all nodes, or a context constructed without seeding an initial node/block.","commonSituations":"Builder UI rendering an automation where the user deleted every step; a test or extension constructing a chain context manually and forgetting the first node; upstream filtering (enabled=false, block missing) removing all nodes before render.","solutions":["Ensure the automation chain being rendered contains at least one node before calling renderChain.","Add a guard in the caller: skip rendering (or render an empty-state placeholder) when the node list is empty.","If nodes are filtered out upstream, keep the trigger/root node in the context so the chain is never empty."],"exampleFix":"// before\nrenderChain(context) // context.nodes may be []\n// after\nif (context.nodes.length === 0) return renderEmptyState()\nrenderChain(context)","handlingStrategy":"validation","validationCode":"const canRenderChain = (ctx: ChainRenderContext): boolean =>\n  getLastSource(ctx) != null // or: ctx.nodes.length > 0\n\nif (!canRenderChain(context)) {\n  return renderEmptyStatePlaceholder()\n}\nconst result = renderChain(context)","typeGuard":"const hasChainSource = (ctx: ChainRenderContext): ctx is ChainRenderContext & { nodes: [Node, ...Node[]] } =>\n  ctx.nodes.length > 0","tryCatchPattern":"let result: ChainRenderResult\ntry {\n  result = renderChain(context)\n} catch (err) {\n  if (err instanceof Error && err.message === \"Cannot render an empty flow chain\") {\n    result = emptyChainRenderResult()\n  } else throw err\n}","preventionTips":["Always keep the trigger/root node in the render context.","Render an explicit empty-state UI when an automation has no steps.","Filter nodes before building the context, not inside the renderer contract."],"tags":["builder","automation","rendering","frontend"],"backgroundTag":"empty-flow-chain","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}