- {validationErrors.filter(e => e.severity === 'error').length} validation error(s) found.
- Please fix them before saving.
+ {/* Validation Summary */}
+ {validationErrors.length > 0 && (
+
+
)}
diff --git a/frontend/src/store/treeEditorStore.ts b/frontend/src/store/treeEditorStore.ts
index ff2a41b3..495e5091 100644
--- a/frontend/src/store/treeEditorStore.ts
+++ b/frontend/src/store/treeEditorStore.ts
@@ -623,6 +623,44 @@ export const useTreeEditorStore = create
()(
validateNode(state.treeStructure)
+ // Check for circular references in next_node_id chains
+ const detectCircularRefs = (startId: string, visited: Set = new Set()): boolean => {
+ if (visited.has(startId)) return true
+ visited.add(startId)
+
+ const node = findNodeInTree(startId, state.treeStructure)
+ if (!node) return false
+
+ // Check options
+ if (node.options) {
+ for (const opt of node.options) {
+ if (opt.next_node_id && detectCircularRefs(opt.next_node_id, new Set(visited))) {
+ errors.push({
+ nodeId: node.id,
+ message: `Circular reference detected: "${opt.label}" creates a loop`,
+ severity: 'error'
+ })
+ return true
+ }
+ }
+ }
+
+ // Check next_node_id
+ if (node.next_node_id && detectCircularRefs(node.next_node_id, new Set(visited))) {
+ errors.push({
+ nodeId: node.id,
+ message: `Circular reference detected in node "${node.title || node.id}"`,
+ severity: 'error'
+ })
+ return true
+ }
+
+ return false
+ }
+
+ // Run from root
+ detectCircularRefs('root')
+
// Check for at least one solution
if (!hasSolution) {
errors.push({