diff --git a/drools-core/src/main/java/org/drools/reteoo/BetaNode.java b/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
--- a/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
+++ b/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
@@ -272,17 +272,22 @@ public abstract class BetaNode extends L
                 workingMemories[i].clearNodeMemory( this );
             }
         }
+        
+        // check if the left node was visited before walking over the right edge.
+        // it may be that right has leftInput indirectly as source, and even if then right has removed the sink
+        // and marked leftInput as visited we still have leftInput pointing to us (but not we back there!)
+        // XXX: this needs a lot of verification!
+        boolean needRemoveFromLeft = !context.alreadyVisited( this.leftInput );
         this.rightInput.remove( context,
                                 builder,
                                 this,
                                 workingMemories );
-        if ( !context.alreadyVisited( this.leftInput ) ) {
+        if ( needRemoveFromLeft ) {
             this.leftInput.remove( context,
                                    builder,
                                    this,
                                    workingMemories );
         }
-
     }
 
     public boolean isObjectMemoryEnabled() {
diff --git a/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java b/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java
--- a/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java
+++ b/drools-core/src/main/java/org/drools/reteoo/ObjectSource.java
@@ -160,6 +160,7 @@ public abstract class ObjectSource exten
         }
 
         if ( this.sink instanceof SingleObjectSinkAdapter ) {
+            assert ((SingleObjectSinkAdapter) sink).sink == objectSink : "Cannot remove non-existing sink";
             this.sink = EmptyObjectSinkAdapter.getInstance();
         } else {
             final CompositeObjectSinkAdapter sinkAdapter = (CompositeObjectSinkAdapter) this.sink;
diff --git a/drools-core/src/main/java/org/drools/reteoo/BetaNode.java b/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
--- a/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
+++ b/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
@@ -278,15 +278,19 @@ public abstract class BetaNode extends L
         // and marked leftInput as visited we still have leftInput pointing to us (but not we back there!)
         // XXX: this needs a lot of verification!
         boolean needRemoveFromLeft = !context.alreadyVisited( this.leftInput );
+        
         this.rightInput.remove( context,
                                 builder,
                                 this,
                                 workingMemories );
         if ( needRemoveFromLeft ) {
-            this.leftInput.remove( context,
+            RuleRemovalContext leftContext = new RuleRemovalContext();
+            this.leftInput.remove( leftContext,
                                    builder,
                                    this,
                                    workingMemories );
+            // Merge the two contexts together.
+            context.merge( leftContext );
         }
     }
 
diff --git a/drools-core/src/main/java/org/drools/reteoo/RuleRemovalContext.java b/drools-core/src/main/java/org/drools/reteoo/RuleRemovalContext.java
--- a/drools-core/src/main/java/org/drools/reteoo/RuleRemovalContext.java
+++ b/drools-core/src/main/java/org/drools/reteoo/RuleRemovalContext.java
@@ -76,4 +76,8 @@ public class RuleRemovalContext
     public void clear() {
         this.visitedNodes.clear();
     }
+    
+    public void merge(RuleRemovalContext other) {
+        this.visitedNodes.putAll( other.visitedNodes );
+    }
 }
diff --git a/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java b/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java
--- a/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java
+++ b/drools-core/src/main/java/org/drools/reteoo/LeftTupleSource.java
@@ -129,6 +129,7 @@ public abstract class LeftTupleSource ex
         }
 
         if ( this.sink instanceof SingleLeftTupleSinkAdapter ) {
+            assert ((SingleLeftTupleSinkAdapter) sink).sink == tupleSink : "Cannot remove non-existing sink";
             this.sink = EmptyLeftTupleSinkAdapter.getInstance();
         } else {
             final CompositeLeftTupleSinkAdapter sinkAdapter = (CompositeLeftTupleSinkAdapter) this.sink;
