We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Exit gracefully when misconfigured
Currently if `mkdocs.yaml` does not exist or if `pages`/`project_name` are not set, we'll exit with an exception.  Really we should print a simple error to stderr and exit with an appropriate error code.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mkdocs/config.py`
Content:
```
1 # coding: utf-8
2 
3 from mkdocs import utils
4 from mkdocs.compat import urlparse
5 import os
6 import yaml
7 
8 DEFAULT_CONFIG = {
9     'site_name': None,
10     'pages': None,
11 
12     'site_url': None,
13     'site_description': None,
14     'site_author': None,
15     'site_favicon': None,
16 
17     'theme': 'mkdocs',
18     'docs_dir': 'docs',
19     'site_dir': 'site',
20     'theme_dir': None,
21 
22     'copyright': None,
23     'google-analytics': None,
24 
25     # The address on which to serve the livereloading docs server.
26     'dev_addr': '127.0.0.1:8000',
27 
28     # If `True`, use `<page_name>/index.hmtl` style files with hyperlinks to the directory.
29     # If `False`, use `<page_name>.html style file with hyperlinks to the file.
30     # True generates nicer URLs, but False is useful if browsing the output on a filesystem.
31     'use_directory_urls': True,
32 
33     # Specify a link to the project source repo to be included
34     # in the documentation pages.
35     'repo_url': None,
36 
37     # A name to use for the link to the project source repo.
38     # Default: If repo_url is unset then None, otherwise
39     # "GitHub" or "Bitbucket" for known url or Hostname for unknown urls.
40     'repo_name': None,
41 
42     # Specify which css or javascript files from the docs
43     # directionary should be additionally included in the site.
44     # Default: List of all .css and .js files in the docs dir.
45     'extra_css': None,
46     'extra_javascript': None,
47 
48     # Determine if the site should include the nav and next/prev elements.
49     # Default: True if the site has more than one page, False otherwise.
50     'include_nav': None,
51     'include_next_prev': None,
52 
53     # PyMarkdown extension names.
54     'markdown_extensions': (),
55 
56     # Determine if the site should generate a json search index and include
57     # search elements in the theme. - TODO
58     'include_search': False,
59 
60     # Determine if the site should include a 404.html page.
61     # TODO: Implment this. Make this None, have it True if a 404.html
62     # template exists in the theme or docs dir.
63     'include_404': False,
64 
65     # Determine if the site should include a sitemap.xml page.
66     # TODO: Implement this. Make this None, have it True if a sitemap.xml
67     # template exists in the theme or docs dir.
68     'include_sitemap': False,
69 }
70 
71 
72 def load_config(filename='mkdocs.yml', options=None):
73     options = options or {}
74     if 'config' in options:
75         filename = options['config']
76     assert os.path.exists(filename), "Config file '%s' does not exist." % filename
77     with open(filename, 'r') as fp:
78         user_config = yaml.load(fp)
79     user_config.update(options)
80     return validate_config(user_config)
81 
82 
83 def validate_config(user_config):
84     config = DEFAULT_CONFIG.copy()
85     config.update(user_config)
86 
87     assert config['site_name'], "Config must contain 'site_name' setting."
88 
89     # If not specified, then the 'pages' config simply includes all
90     # markdown files in the docs dir, without generating any header items
91     # for them.
92     pages = []
93     extra_css = []
94     extra_javascript = []
95     for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):
96         for filename in sorted(filenames):
97             fullpath = os.path.join(dirpath, filename)
98             relpath = os.path.relpath(fullpath, config['docs_dir'])
99 
100             if utils.is_markdown_file(filename):
101                 # index pages should always be the first listed page.
102                 if os.path.splitext(relpath)[0] == 'index':
103                     pages.insert(0, relpath)
104                 else:
105                     pages.append(relpath)
106             elif utils.is_css_file(filename):
107                 extra_css.append(relpath)
108             elif utils.is_javascript_file(filename):
109                 extra_javascript.append(relpath)
110 
111     if config['pages'] is None:
112         config['pages'] = pages
113 
114     if config['extra_css'] is None:
115         config['extra_css'] = extra_css
116 
117     if config['extra_javascript'] is None:
118         config['extra_javascript'] = extra_javascript
119 
120     package_dir = os.path.dirname(__file__)
121     theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]
122 
123     if config['theme_dir'] is not None:
124         theme_dir.insert(0, config['theme_dir'])
125 
126     config['theme_dir'] = theme_dir
127 
128     if config['repo_url'] is not None and config['repo_name'] is None:
129         repo_host = urlparse(config['repo_url']).netloc.lower()
130         if repo_host == 'github.com':
131             config['repo_name'] = 'GitHub'
132         elif repo_host == 'bitbucket.com':
133             config['repo_name'] = 'Bitbucket'
134         else:
135             config['repo_name'] = repo_host.split('.')[0].title()
136 
137     if config['include_next_prev'] is None:
138         config['include_next_prev'] = len(config['pages']) > 1
139 
140     if config['include_nav'] is None:
141         config['include_nav'] = len(config['pages']) > 1
142 
143     # To Do:
144 
145     # The docs dir must exist.
146     # The theme dir must exist.
147     # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'
148     # A homepage 'index' must exist.
149     # The theme 'base.html' file must exist.
150     # Cannot set repo_name without setting repo_url.
151     # Cannot set 'include_next_prev: true' when only one page exists.
152     # Cannot set 'include_nav: true' when only one page exists.
153     # Error if any config keys provided that are not in the DEFAULT_CONFIG.
154 
155     return config
156
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mkdocs/config.py b/mkdocs/config.py
--- a/mkdocs/config.py
+++ b/mkdocs/config.py
@@ -2,7 +2,9 @@
 
 from mkdocs import utils
 from mkdocs.compat import urlparse
+import errno
 import os
+import sys
 import yaml
 
 DEFAULT_CONFIG = {
@@ -73,7 +75,9 @@
     options = options or {}
     if 'config' in options:
         filename = options['config']
-    assert os.path.exists(filename), "Config file '%s' does not exist." % filename
+    if not os.path.exists(filename):
+        sys.stderr.write("Config file '%s' does not exist." % filename)
+        sys.exit(errno.ENOENT)
     with open(filename, 'r') as fp:
         user_config = yaml.load(fp)
     user_config.update(options)
@@ -84,7 +88,9 @@
     config = DEFAULT_CONFIG.copy()
     config.update(user_config)
 
-    assert config['site_name'], "Config must contain 'site_name' setting."
+    if not config['site_name']:
+        sys.stderr.write("Config must contain 'site_name' setting.")
+        sys.exit(errno.EINVAL)
 
     # If not specified, then the 'pages' config simply includes all
     # markdown files in the docs dir, without generating any header items

{"golden_diff": "diff --git a/mkdocs/config.py b/mkdocs/config.py\n--- a/mkdocs/config.py\n+++ b/mkdocs/config.py\n@@ -2,7 +2,9 @@\n \n from mkdocs import utils\n from mkdocs.compat import urlparse\n+import errno\n import os\n+import sys\n import yaml\n \n DEFAULT_CONFIG = {\n@@ -73,7 +75,9 @@\n     options = options or {}\n     if 'config' in options:\n         filename = options['config']\n-    assert os.path.exists(filename), \"Config file '%s' does not exist.\" % filename\n+    if not os.path.exists(filename):\n+        sys.stderr.write(\"Config file '%s' does not exist.\" % filename)\n+        sys.exit(errno.ENOENT)\n     with open(filename, 'r') as fp:\n         user_config = yaml.load(fp)\n     user_config.update(options)\n@@ -84,7 +88,9 @@\n     config = DEFAULT_CONFIG.copy()\n     config.update(user_config)\n \n-    assert config['site_name'], \"Config must contain 'site_name' setting.\"\n+    if not config['site_name']:\n+        sys.stderr.write(\"Config must contain 'site_name' setting.\")\n+        sys.exit(errno.EINVAL)\n \n     # If not specified, then the 'pages' config simply includes all\n     # markdown files in the docs dir, without generating any header items\n", "issue": "Exit gracefully when misconfigured\nCurrently if `mkdocs.yaml` does not exist or if `pages`/`project_name` are not set, we'll exit with an exception.  Really we should print a simple error to stderr and exit with an appropriate error code.\n\n", "before_files": [{"content": "# coding: utf-8\n\nfrom mkdocs import utils\nfrom mkdocs.compat import urlparse\nimport os\nimport yaml\n\nDEFAULT_CONFIG = {\n    'site_name': None,\n    'pages': None,\n\n    'site_url': None,\n    'site_description': None,\n    'site_author': None,\n    'site_favicon': None,\n\n    'theme': 'mkdocs',\n    'docs_dir': 'docs',\n    'site_dir': 'site',\n    'theme_dir': None,\n\n    'copyright': None,\n    'google-analytics': None,\n\n    # The address on which to serve the livereloading docs server.\n    'dev_addr': '127.0.0.1:8000',\n\n    # If `True`, use `<page_name>/index.hmtl` style files with hyperlinks to the directory.\n    # If `False`, use `<page_name>.html style file with hyperlinks to the file.\n    # True generates nicer URLs, but False is useful if browsing the output on a filesystem.\n    'use_directory_urls': True,\n\n    # Specify a link to the project source repo to be included\n    # in the documentation pages.\n    'repo_url': None,\n\n    # A name to use for the link to the project source repo.\n    # Default: If repo_url is unset then None, otherwise\n    # \"GitHub\" or \"Bitbucket\" for known url or Hostname for unknown urls.\n    'repo_name': None,\n\n    # Specify which css or javascript files from the docs\n    # directionary should be additionally included in the site.\n    # Default: List of all .css and .js files in the docs dir.\n    'extra_css': None,\n    'extra_javascript': None,\n\n    # Determine if the site should include the nav and next/prev elements.\n    # Default: True if the site has more than one page, False otherwise.\n    'include_nav': None,\n    'include_next_prev': None,\n\n    # PyMarkdown extension names.\n    'markdown_extensions': (),\n\n    # Determine if the site should generate a json search index and include\n    # search elements in the theme. - TODO\n    'include_search': False,\n\n    # Determine if the site should include a 404.html page.\n    # TODO: Implment this. Make this None, have it True if a 404.html\n    # template exists in the theme or docs dir.\n    'include_404': False,\n\n    # Determine if the site should include a sitemap.xml page.\n    # TODO: Implement this. Make this None, have it True if a sitemap.xml\n    # template exists in the theme or docs dir.\n    'include_sitemap': False,\n}\n\n\ndef load_config(filename='mkdocs.yml', options=None):\n    options = options or {}\n    if 'config' in options:\n        filename = options['config']\n    assert os.path.exists(filename), \"Config file '%s' does not exist.\" % filename\n    with open(filename, 'r') as fp:\n        user_config = yaml.load(fp)\n    user_config.update(options)\n    return validate_config(user_config)\n\n\ndef validate_config(user_config):\n    config = DEFAULT_CONFIG.copy()\n    config.update(user_config)\n\n    assert config['site_name'], \"Config must contain 'site_name' setting.\"\n\n    # If not specified, then the 'pages' config simply includes all\n    # markdown files in the docs dir, without generating any header items\n    # for them.\n    pages = []\n    extra_css = []\n    extra_javascript = []\n    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):\n        for filename in sorted(filenames):\n            fullpath = os.path.join(dirpath, filename)\n            relpath = os.path.relpath(fullpath, config['docs_dir'])\n\n            if utils.is_markdown_file(filename):\n                # index pages should always be the first listed page.\n                if os.path.splitext(relpath)[0] == 'index':\n                    pages.insert(0, relpath)\n                else:\n                    pages.append(relpath)\n            elif utils.is_css_file(filename):\n                extra_css.append(relpath)\n            elif utils.is_javascript_file(filename):\n                extra_javascript.append(relpath)\n\n    if config['pages'] is None:\n        config['pages'] = pages\n\n    if config['extra_css'] is None:\n        config['extra_css'] = extra_css\n\n    if config['extra_javascript'] is None:\n        config['extra_javascript'] = extra_javascript\n\n    package_dir = os.path.dirname(__file__)\n    theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]\n\n    if config['theme_dir'] is not None:\n        theme_dir.insert(0, config['theme_dir'])\n\n    config['theme_dir'] = theme_dir\n\n    if config['repo_url'] is not None and config['repo_name'] is None:\n        repo_host = urlparse(config['repo_url']).netloc.lower()\n        if repo_host == 'github.com':\n            config['repo_name'] = 'GitHub'\n        elif repo_host == 'bitbucket.com':\n            config['repo_name'] = 'Bitbucket'\n        else:\n            config['repo_name'] = repo_host.split('.')[0].title()\n\n    if config['include_next_prev'] is None:\n        config['include_next_prev'] = len(config['pages']) > 1\n\n    if config['include_nav'] is None:\n        config['include_nav'] = len(config['pages']) > 1\n\n    # To Do:\n\n    # The docs dir must exist.\n    # The theme dir must exist.\n    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'\n    # A homepage 'index' must exist.\n    # The theme 'base.html' file must exist.\n    # Cannot set repo_name without setting repo_url.\n    # Cannot set 'include_next_prev: true' when only one page exists.\n    # Cannot set 'include_nav: true' when only one page exists.\n    # Error if any config keys provided that are not in the DEFAULT_CONFIG.\n\n    return config\n", "path": "mkdocs/config.py"}], "after_files": [{"content": "# coding: utf-8\n\nfrom mkdocs import utils\nfrom mkdocs.compat import urlparse\nimport errno\nimport os\nimport sys\nimport yaml\n\nDEFAULT_CONFIG = {\n    'site_name': None,\n    'pages': None,\n\n    'site_url': None,\n    'site_description': None,\n    'site_author': None,\n    'site_favicon': None,\n\n    'theme': 'mkdocs',\n    'docs_dir': 'docs',\n    'site_dir': 'site',\n    'theme_dir': None,\n\n    'copyright': None,\n    'google-analytics': None,\n\n    # The address on which to serve the livereloading docs server.\n    'dev_addr': '127.0.0.1:8000',\n\n    # If `True`, use `<page_name>/index.hmtl` style files with hyperlinks to the directory.\n    # If `False`, use `<page_name>.html style file with hyperlinks to the file.\n    # True generates nicer URLs, but False is useful if browsing the output on a filesystem.\n    'use_directory_urls': True,\n\n    # Specify a link to the project source repo to be included\n    # in the documentation pages.\n    'repo_url': None,\n\n    # A name to use for the link to the project source repo.\n    # Default: If repo_url is unset then None, otherwise\n    # \"GitHub\" or \"Bitbucket\" for known url or Hostname for unknown urls.\n    'repo_name': None,\n\n    # Specify which css or javascript files from the docs\n    # directionary should be additionally included in the site.\n    # Default: List of all .css and .js files in the docs dir.\n    'extra_css': None,\n    'extra_javascript': None,\n\n    # Determine if the site should include the nav and next/prev elements.\n    # Default: True if the site has more than one page, False otherwise.\n    'include_nav': None,\n    'include_next_prev': None,\n\n    # PyMarkdown extension names.\n    'markdown_extensions': (),\n\n    # Determine if the site should generate a json search index and include\n    # search elements in the theme. - TODO\n    'include_search': False,\n\n    # Determine if the site should include a 404.html page.\n    # TODO: Implment this. Make this None, have it True if a 404.html\n    # template exists in the theme or docs dir.\n    'include_404': False,\n\n    # Determine if the site should include a sitemap.xml page.\n    # TODO: Implement this. Make this None, have it True if a sitemap.xml\n    # template exists in the theme or docs dir.\n    'include_sitemap': False,\n}\n\n\ndef load_config(filename='mkdocs.yml', options=None):\n    options = options or {}\n    if 'config' in options:\n        filename = options['config']\n    if not os.path.exists(filename):\n        sys.stderr.write(\"Config file '%s' does not exist.\" % filename)\n        sys.exit(errno.ENOENT)\n    with open(filename, 'r') as fp:\n        user_config = yaml.load(fp)\n    user_config.update(options)\n    return validate_config(user_config)\n\n\ndef validate_config(user_config):\n    config = DEFAULT_CONFIG.copy()\n    config.update(user_config)\n\n    if not config['site_name']:\n        sys.stderr.write(\"Config must contain 'site_name' setting.\")\n        sys.exit(errno.EINVAL)\n\n    # If not specified, then the 'pages' config simply includes all\n    # markdown files in the docs dir, without generating any header items\n    # for them.\n    pages = []\n    extra_css = []\n    extra_javascript = []\n    for (dirpath, dirnames, filenames) in os.walk(config['docs_dir']):\n        for filename in sorted(filenames):\n            fullpath = os.path.join(dirpath, filename)\n            relpath = os.path.relpath(fullpath, config['docs_dir'])\n\n            if utils.is_markdown_file(filename):\n                # index pages should always be the first listed page.\n                if os.path.splitext(relpath)[0] == 'index':\n                    pages.insert(0, relpath)\n                else:\n                    pages.append(relpath)\n            elif utils.is_css_file(filename):\n                extra_css.append(relpath)\n            elif utils.is_javascript_file(filename):\n                extra_javascript.append(relpath)\n\n    if config['pages'] is None:\n        config['pages'] = pages\n\n    if config['extra_css'] is None:\n        config['extra_css'] = extra_css\n\n    if config['extra_javascript'] is None:\n        config['extra_javascript'] = extra_javascript\n\n    package_dir = os.path.dirname(__file__)\n    theme_dir = [os.path.join(package_dir, 'themes', config['theme'])]\n\n    if config['theme_dir'] is not None:\n        theme_dir.insert(0, config['theme_dir'])\n\n    config['theme_dir'] = theme_dir\n\n    if config['repo_url'] is not None and config['repo_name'] is None:\n        repo_host = urlparse(config['repo_url']).netloc.lower()\n        if repo_host == 'github.com':\n            config['repo_name'] = 'GitHub'\n        elif repo_host == 'bitbucket.com':\n            config['repo_name'] = 'Bitbucket'\n        else:\n            config['repo_name'] = repo_host.split('.')[0].title()\n\n    if config['include_next_prev'] is None:\n        config['include_next_prev'] = len(config['pages']) > 1\n\n    if config['include_nav'] is None:\n        config['include_nav'] = len(config['pages']) > 1\n\n    # To Do:\n\n    # The docs dir must exist.\n    # The theme dir must exist.\n    # Ensure 'theme' is one of 'mkdocs', 'readthedocs', 'custom'\n    # A homepage 'index' must exist.\n    # The theme 'base.html' file must exist.\n    # Cannot set repo_name without setting repo_url.\n    # Cannot set 'include_next_prev: true' when only one page exists.\n    # Cannot set 'include_nav: true' when only one page exists.\n    # Error if any config keys provided that are not in the DEFAULT_CONFIG.\n\n    return config\n", "path": "mkdocs/config.py"}]}