Repository: mkdocs/mkdocs

Issue:
MkDocs aborts serve if there are warnings for HTTP 404 errors
I was trying out MkDocs 1.2.2 and noticed the following change of behavior from 1.1.2:

When running `mkdocs serve` with strict mode, MkDocs stops on the first update to a page if there were any warnings for HTTP 404 errors:

```console
$ mkdocs -V
mkdocs, version 1.2.2 from /home/prcr/.local/lib/python3.6/site-packages/mkdocs (Python 3.6)
$ mkdocs serve
INFO     -  Building documentation...
INFO     -  Cleaning site directory
INFO     -  Documentation built in 4.24 seconds
INFO     -  [11:48:31] Serving on http://127.0.0.1:8000/
INFO     -  [11:48:33] Browser connected: http://127.0.0.1:8000/special-thanks/
WARNING  -  [11:48:33] "GET /versions.json HTTP/1.1" code 404
INFO     -  [11:48:45] Detected file changes
INFO     -  Building documentation...
INFO     -  [11:48:50] Reloading browsers
INFO     -  [11:48:50] Browser connected: http://127.0.0.1:8000/special-thanks/
WARNING  -  [11:48:50] "GET /versions.json HTTP/1.1" code 404
INFO     -  [11:49:14] Detected file changes
INFO     -  Building documentation...

Aborted with 2 warnings in strict mode!
```

MkDocs 1.1.2 ignored the same warnings when also running in strict mode:

```console
$ mkdocs -V
mkdocs, version 1.1.2 from /home/prcr/.local/lib/python3.6/site-packages/mkdocs (Python 3.6)
$ mkdocs serve
INFO    -  Building documentation... 
INFO    -  Cleaning site directory 
INFO    -  Documentation built in 5.50 seconds 
[I 210901 11:51:33 server:335] Serving on http://127.0.0.1:8000
INFO    -  Serving on http://127.0.0.1:8000
[I 210901 11:51:33 handlers:62] Start watching changes
INFO    -  Start watching changes
[W 210901 11:51:34 web:2243] 404 GET /versions.json (127.0.0.1) 6.18ms
WARNING -  404 GET /versions.json (127.0.0.1) 6.18ms
[I 210901 11:51:34 handlers:135] Browser Connected: http://127.0.0.1:8000/
INFO    -  Browser Connected: http://127.0.0.1:8000/
[I 210901 11:51:40 watcher:111] Running task: builder (delay: None)
INFO    -  Running task: builder (delay: None)
INFO    -  Building documentation... 
[I 210901 11:51:45 handlers:95] Reload 1 waiters: /home/prcr/Codacy/git/docs/submodules/chart/docs/maintenance/uninstall.md
INFO    -  Reload 1 waiters: /home/prcr/Codacy/git/docs/submodules/chart/docs/maintenance/uninstall.md
[I 210901 11:51:46 handlers:82] Ignore: /home/prcr/Codacy/git/docs/docs/related-tools/local-analysis/images/run-analysis-through-build-server.png
INFO    -  Ignore: /home/prcr/Codacy/git/docs/docs/related-tools/local-analysis/images/run-analysis-through-build-server.png
[W 210901 11:51:46 web:2243] 404 GET /versions.json (127.0.0.1) 5.92ms
WARNING -  404 GET /versions.json (127.0.0.1) 5.92ms
[I 210901 11:51:46 handlers:135] Browser Connected: http://127.0.0.1:8000/
INFO    -  Browser Connected: http://127.0.0.1:8000/
```

I wonder if it was a conscious decision to change this behavior in MkDocs 1.2 or if we could go back to the previous behavior of (safely) ignoring the HTTP 404 errors when serving the pages.


Discussion:

Resolving patch:
diff --git a/mkdocs/__main__.py b/mkdocs/__main__.py
--- a/mkdocs/__main__.py
+++ b/mkdocs/__main__.py
@@ -63,11 +63,6 @@ def __init__(self, log_name='mkdocs', level=logging.INFO):
         self.stream.name = 'MkDocsStreamHandler'
         self.logger.addHandler(self.stream)
 
-        # Add CountHandler for strict mode
-        self.counter = utils.log_counter
-        self.counter.setLevel(logging.WARNING)
-        self.logger.addHandler(self.counter)
-
 
 pass_state = click.make_pass_decorator(State, ensure=True)
 
diff --git a/mkdocs/commands/build.py b/mkdocs/commands/build.py
--- a/mkdocs/commands/build.py
+++ b/mkdocs/commands/build.py
@@ -240,8 +240,16 @@ def _build_page(page, config, doc_files, nav, env, dirty=False):
 
 def build(config, live_server=False, dirty=False):
     """ Perform a full site build. """
-    try:
 
+    logger = logging.getLogger('mkdocs')
+
+    # Add CountHandler for strict mode
+    warning_counter = utils.CountHandler()
+    warning_counter.setLevel(logging.WARNING)
+    if config['strict']:
+        logging.getLogger('mkdocs').addHandler(warning_counter)
+
+    try:
         from time import time
         start = time()
 
@@ -308,8 +316,8 @@ def build(config, live_server=False, dirty=False):
         # Run `post_build` plugin events.
         config['plugins'].run_event('post_build', config=config)
 
-        counts = utils.log_counter.get_counts()
-        if config['strict'] and len(counts):
+        counts = warning_counter.get_counts()
+        if counts:
             msg = ', '.join([f'{v} {k.lower()}s' for k, v in counts])
             raise Abort(f'\nAborted with {msg} in strict mode!')
 
@@ -323,6 +331,9 @@ def build(config, live_server=False, dirty=False):
             raise Abort('\nAborted with a BuildError!')
         raise
 
+    finally:
+        logger.removeHandler(warning_counter)
+
 
 def site_directory_contains_stale_files(site_directory):
     """ Check if the site directory contains stale files from a previous build. """
diff --git a/mkdocs/utils/__init__.py b/mkdocs/utils/__init__.py
--- a/mkdocs/utils/__init__.py
+++ b/mkdocs/utils/__init__.py
@@ -442,9 +442,6 @@ def get_counts(self):
         return [(logging.getLevelName(k), v) for k, v in sorted(self.counts.items(), reverse=True)]
 
 
-# A global instance to use throughout package
-log_counter = CountHandler()
-
 # For backward compatibility as some plugins import it.
 # It is no longer necessary as all messages on the
 # `mkdocs` logger get counted automatically.


Test patch: