code: def test_recovers_from_build_error(self, site_dir, docs_dir):
      started_building = threading.Event()
      build_count = 0
  
      def rebuild():
          started_building.set()
          nonlocal build_count
          build_count += 1
          if build_count == 1:
              raise ValueError("oh no")
          else:
              content = Path(docs_dir, "foo.docs").read_text()
              Path(site_dir, "foo.site").write_text(content * 5)
  
      with testing_server(site_dir, rebuild) as server:
          server.watch(docs_dir)
          time.sleep(0.01)
  
          err = io.StringIO()
          with contextlib.redirect_stderr(err), self.assertLogs(
              "mkdocs.livereload"
          ) as cm:
              Path(docs_dir, "foo.docs").write_text("b")
              started_building.wait(timeout=10)
  
              Path(docs_dir, "foo.docs").write_text("c")
  
              _, output = do_request(server, "GET /foo.site")
  
          self.assertIn("ValueError: oh no", err.getvalue())
          self.assertRegex(
              "\n".join(cm.output),
              r".*Detected file changes\n"
              r".*An error happened during the rebuild.*\n"
              r".*Detected file changes\n",
          )
          self.assertEqual(output, "ccccc")
  
imports: import contextlib
  import email
  import io
  import sys
  import threading
  import time
  import unittest
  from pathlib import Path
  from unittest import mock
  from mkdocs.livereload import LiveReloadServer
  from mkdocs.tests.base import change_dir, tempdir
label_desc: Use image node_id 10 for calling the BuildTests obj's underlying member method code with example usage: obj.test_recovers_from_build_error(site_dir, docs_dir) without return types