Skip to main content
This guide helps you diagnose and fix common issues when working with Vue Flow. Learn about error codes, debugging strategies, and solutions to frequent problems.

Error codes

Vue Flow emits specific error codes to help you identify issues quickly. Errors are logged to the console in development and can be caught using the onError event handler.

MISSING_VIEWPORT_DIMENSIONS

The Vue Flow container needs explicit dimensions to render correctly.
Vue Flow cannot render without a defined width and height on its parent container.
Solution:
<template>
  <!-- Set explicit dimensions on the parent container -->
  <div style="width: 100%; height: 100vh;">
    <VueFlow :nodes="nodes" :edges="edges" />
  </div>
</template>
Or use CSS:
.flow-container {
  width: 100%;
  height: 100vh;
}
<template>
  <div class="flow-container">
    <VueFlow :nodes="nodes" :edges="edges" />
  </div>
</template>

NODE_INVALID

A node configuration is invalid or missing required properties. Common causes:
  • Missing id property
  • Missing position property
  • Invalid position format
Solution:
// Invalid - missing position
const invalidNode = {
  id: '1',
  data: { label: 'Node' },
}

// Valid
const validNode = {
  id: '1',
  position: { x: 0, y: 0 },
  data: { label: 'Node' },
}

NODE_NOT_FOUND

Attempting to access a node that doesn’t exist in the graph. Common causes:
  • Using useNode() outside a node component without a valid ID
  • Referencing a deleted node
  • Typo in node ID
Solution:
import { useVueFlow } from '@vue-flow/core'

const { findNode } = useVueFlow()

const node = findNode('1')

if (node) {
  // Node exists, safe to use
  console.log(node.data)
} else {
  console.error('Node not found')
}

NODE_MISSING_PARENT

A child node references a parent that doesn’t exist. Solution: Ensure parent nodes are added before their children:
const nodes = ref([
  // Add parent first
  {
    id: 'parent',
    position: { x: 0, y: 0 },
    data: { label: 'Parent' },
  },
  // Then add child
  {
    id: 'child',
    position: { x: 50, y: 50 },
    parentNode: 'parent',  // References parent above
    data: { label: 'Child' },
  },
])

NODE_TYPE_MISSING

A node’s type has no corresponding component defined. Solution: Register all custom node types:
<script setup>
import { markRaw } from 'vue'
import CustomNode from './CustomNode.vue'

const nodeTypes = {
  custom: markRaw(CustomNode),
}
</script>

<template>
  <!-- Register via prop -->
  <VueFlow :nodes="nodes" :node-types="nodeTypes" />
  
  <!-- OR via template slot -->
  <VueFlow :nodes="nodes">
    <template #node-custom="props">
      <CustomNode v-bind="props" />
    </template>
  </VueFlow>
</template>

NODE_EXTENT_INVALID

Only child nodes can use the parent extent. Solution:
const nodes = ref([
  {
    id: 'parent',
    position: { x: 0, y: 0 },
    data: { label: 'Parent' },
    // Cannot use 'parent' extent on root node
  },
  {
    id: 'child',
    position: { x: 50, y: 50 },
    parentNode: 'parent',
    extent: 'parent',  // Valid - this is a child node
    data: { label: 'Child' },
  },
])

EDGE_INVALID

An edge is missing required properties. Common causes:
  • Missing source or target
  • Missing id
Solution:
// Invalid - missing id
const invalidEdge = {
  source: '1',
  target: '2',
}

// Valid
const validEdge = {
  id: 'e1-2',
  source: '1',
  target: '2',
}

EDGE_NOT_FOUND

Attempting to access an edge that doesn’t exist. Solution:
import { useVueFlow } from '@vue-flow/core'

const { findEdge } = useVueFlow()

const edge = findEdge('e1-2')

if (edge) {
  // Edge exists
  console.log(edge.source, edge.target)
} else {
  console.error('Edge not found')
}

EDGE_SOURCE_MISSING / EDGE_TARGET_MISSING

An edge references a source or target node that doesn’t exist. Solution: Ensure nodes exist before creating edges:
const nodes = ref([
  { id: '1', position: { x: 0, y: 0 }, data: {} },
  { id: '2', position: { x: 200, y: 0 }, data: {} },
])

const edges = ref([
  {
    id: 'e1-2',
    source: '1',  // Node '1' exists
    target: '2',  // Node '2' exists
  },
])

EDGE_TYPE_MISSING

An edge’s type has no corresponding component. Solution:
<script setup>
import { markRaw } from 'vue'
import CustomEdge from './CustomEdge.vue'

const edgeTypes = {
  custom: markRaw(CustomEdge),
}
</script>

<template>
  <VueFlow :edges="edges" :edge-types="edgeTypes" />
</template>

EDGE_SOURCE_TARGET_SAME

An edge’s source and target are the same node. This is often intentional for self-referencing nodes. You can safely ignore this warning.

EDGE_ORPHANED

An edge lost its source or target node, likely due to node deletion. Solution: Remove edges when deleting their connected nodes:
import { useVueFlow } from '@vue-flow/core'

const { removeNodes, edges } = useVueFlow()

function deleteNode(nodeId: string) {
  // Remove connected edges first
  const connectedEdges = edges.value.filter(
    (e) => e.source === nodeId || e.target === nodeId
  )
  removeEdges(connectedEdges.map((e) => e.id))
  
  // Then remove the node
  removeNodes(nodeId)
}

Handling errors

Catch and handle errors programmatically:
<script setup lang="ts">
import { useVueFlow, isErrorOfType, ErrorCode, VueFlowError } from '@vue-flow/core'

const { onError } = useVueFlow()

onError(handleError)

function handleError(error: VueFlowError) {
  // Check specific error types
  if (isErrorOfType(error, ErrorCode.NODE_INVALID)) {
    const [nodeId] = error.args
    console.error('Invalid node:', nodeId)
  }
  
  if (isErrorOfType(error, ErrorCode.EDGE_SOURCE_MISSING)) {
    const [edgeId, sourceId] = error.args
    console.error('Edge', edgeId, 'has missing source:', sourceId)
  }
  
  // Log all errors
  console.error(error.message, error)
}
</script>

<template>
  <VueFlow @error="handleError" />
</template>

Common issues

Nodes not rendering

Ensure the parent container has explicit width and height:
<template>
  <div style="width: 100%; height: 100vh;">
    <VueFlow :nodes="nodes" :edges="edges" />
  </div>
</template>
Import required Vue Flow styles:
@import '@vue-flow/core/dist/style.css';
@import '@vue-flow/core/dist/theme-default.css';
Use fitView to center nodes:
<template>
  <VueFlow :nodes="nodes" fit-view-on-init />
</template>
Or programmatically:
import { useVueFlow } from '@vue-flow/core'

const { fitView } = useVueFlow()

onMounted(() => {
  fitView()
})

Edges not connecting

Ensure your custom nodes have handles:
<script setup>
import { Handle, Position } from '@vue-flow/core'
</script>

<template>
  <div>
    <Handle type="target" :position="Position.Top" />
    <!-- Node content -->
    <Handle type="source" :position="Position.Bottom" />
  </div>
</template>
Check the connectable prop:
<template>
  <VueFlow 
    :nodes="nodes" 
    :edges="edges"
    :nodes-connectable="true"
  />
</template>
Or per node:
const nodes = ref([
  {
    id: '1',
    position: { x: 0, y: 0 },
    connectable: true,  // Enable connections
    data: {},
  },
])
Check your connection validation logic:
import type { Connection } from '@vue-flow/core'

function isValidConnection(connection: Connection) {
  console.log('Validating connection:', connection)
  // Your validation logic
  return true
}
<template>
  <VueFlow 
    :nodes="nodes" 
    :edges="edges"
    :is-valid-connection="isValidConnection"
  />
</template>

Drag and drop not working

Add nodrag class to interactive elements:
<template>
  <div>
    <input class="nodrag" type="text" />
    <button class="nodrag">Click me</button>
  </div>
</template>
If using a drag handle, ensure it exists:
const nodes = ref([
  {
    id: '1',
    position: { x: 0, y: 0 },
    dragHandle: '.drag-area',  // Must exist in component
    data: {},
  },
])
<template>
  <div>
    <div class="drag-area">Drag from here</div>
    <div class="nodrag">Can't drag from here</div>
  </div>
</template>

Performance issues

Use viewport optimization:
<template>
  <VueFlow 
    :nodes="nodes" 
    :edges="edges"
    :only-render-visible-elements="true"
  />
</template>
Wrap components with markRaw():
import { markRaw } from 'vue'
import CustomNode from './CustomNode.vue'

const nodeTypes = {
  custom: markRaw(CustomNode),  // Prevents reactivity
}
Use computed and memoization:
<script setup>
import { computed } from 'vue'

const props = defineProps(['data'])

const expensiveValue = computed(() => {
  // Expensive computation
  return heavyCalculation(props.data)
})
</script>

Debugging tips

Enable dev tools

<script setup>
import { useVueFlow } from '@vue-flow/core'

const { nodes, edges, getNodes, getEdges } = useVueFlow()

// Expose for debugging
if (import.meta.env.DEV) {
  window.vueFlowDebug = {
    nodes: () => console.table(getNodes()),
    edges: () => console.table(getEdges()),
    state: () => console.log({ nodes: nodes.value, edges: edges.value }),
  }
}
</script>
Access in browser console:
vueFlowDebug.nodes()
vueFlowDebug.edges()
vueFlowDebug.state()

Log events

<script setup>
import { useVueFlow } from '@vue-flow/core'

const { 
  onNodeClick,
  onEdgeClick,
  onConnect,
  onNodesChange,
  onEdgesChange,
} = useVueFlow()

if (import.meta.env.DEV) {
  onNodeClick((e) => console.log('Node click:', e))
  onEdgeClick((e) => console.log('Edge click:', e))
  onConnect((c) => console.log('Connect:', c))
  onNodesChange((c) => console.log('Nodes change:', c))
  onEdgesChange((c) => console.log('Edges change:', c))
}
</script>

Inspect internal state

Use Vue DevTools to inspect Vue Flow’s internal state:
  1. Open Vue DevTools
  2. Find the VueFlow component
  3. Inspect the component’s state and props

Getting help

If you’re still experiencing issues:
  1. Check the examples for similar use cases
  2. Search GitHub issues
  3. Create a minimal reproduction on StackBlitz
  4. Ask on Discord

Next steps

Examples

Explore working examples

API reference

Complete API documentation

Build docs developers (and LLMs) love