diff --git a/rhodecode/lib/middleware/simplevcs.py b/rhodecode/lib/middleware/simplevcs.py
--- a/rhodecode/lib/middleware/simplevcs.py
+++ b/rhodecode/lib/middleware/simplevcs.py
@@ -238,6 +238,10 @@ class SimpleVCS(object):
 
         return False
 
+    @property
+    def is_shadow_repo_dir(self):
+        return os.path.isdir(self.vcs_repo_name)
+
     def _check_permission(self, action, user, repo_name, ip_addr=None):
         """
         Checks permissions using action (push/pull) user and repository
@@ -331,6 +335,11 @@ class SimpleVCS(object):
             log.debug('User not allowed to proceed, %s', reason)
             return HTTPNotAcceptable(reason)(environ, start_response)
 
+        # Check if the shadow repo actually exists, in case someone refers
+        # to it, and it has been deleted because of successful merge.
+        if self.is_shadow_repo and not self.is_shadow_repo_dir:
+            return HTTPNotFound()(environ, start_response)
+
         # ======================================================================
         # CHECK ANONYMOUS PERMISSION
         # ======================================================================
diff --git a/rhodecode/tests/lib/middleware/test_simplevcs.py b/rhodecode/tests/lib/middleware/test_simplevcs.py
--- a/rhodecode/tests/lib/middleware/test_simplevcs.py
+++ b/rhodecode/tests/lib/middleware/test_simplevcs.py
@@ -45,9 +45,14 @@ class StubVCSController(simplevcs.Simple
     def __init__(self, *args, **kwargs):
         super(StubVCSController, self).__init__(*args, **kwargs)
         self._action = 'pull'
+        self._is_shadow_repo_dir = True
         self._name = HG_REPO
         self.set_repo_names(None)
 
+    @property
+    def is_shadow_repo_dir(self):
+        return self._is_shadow_repo_dir
+
     def _get_repository_name(self, environ):
         return self._name
 
@@ -218,6 +223,7 @@ class TestShadowRepoExposure(object):
         controller._check_ssl = mock.Mock()
         controller.is_shadow_repo = True
         controller._action = 'pull'
+        controller._is_shadow_repo_dir = True
         controller.stub_response_body = 'dummy body value'
         environ_stub = {
             'HTTP_HOST': 'test.example.com',
@@ -232,6 +238,30 @@ class TestShadowRepoExposure(object):
         # Assert that we got the response from the wsgi app.
         assert response_body == controller.stub_response_body
 
+    def test_pull_on_shadow_repo_that_is_missing(self, pylonsapp):
+        """
+        Check that a pull action to a shadow repo is propagated to the
+        underlying wsgi app.
+        """
+        controller = StubVCSController(pylonsapp, pylonsapp.config, None)
+        controller._check_ssl = mock.Mock()
+        controller.is_shadow_repo = True
+        controller._action = 'pull'
+        controller._is_shadow_repo_dir = False
+        controller.stub_response_body = 'dummy body value'
+        environ_stub = {
+            'HTTP_HOST': 'test.example.com',
+            'HTTP_ACCEPT': 'application/mercurial',
+            'REQUEST_METHOD': 'GET',
+            'wsgi.url_scheme': 'http',
+        }
+
+        response = controller(environ_stub, mock.Mock())
+        response_body = ''.join(response)
+
+        # Assert that we got the response from the wsgi app.
+        assert '404 Not Found' in response_body
+
     def test_push_on_shadow_repo_raises(self, pylonsapp):
         """
         Check that a push action to a shadow repo is aborted.