diff --git a/docs/about/release-notes.md b/docs/about/release-notes.md
index 426ef3c8..b8d9926b 100644
--- a/docs/about/release-notes.md
+++ b/docs/about/release-notes.md
@@ -64,9 +64,9 @@ created and third-party templates:
 #### Increased Template Customization. (#607)
 
 The built-in themes have been updated by having each of their many parts wrapped
-in template blocks which allow each individual block to be easily overriden
+in template blocks which allow each individual block to be easily overridden
 using the `theme_dir` config setting. Without any new settings, you can use a
-differant analytics service, replace the default search function, or alter the
+different analytics service, replace the default search function, or alter the
 behavior of the navigation, among other things. See the relevant
 [documentation][blocks] for more details.
 
@@ -112,16 +112,26 @@ It is important to note that this method for building the pages is for developme
 of content only, since the navigation and other links do not get updated on other
 pages.
 
+#### Stricter Directory Validation
+
+Previously, a warning was issued if the `site_dir` was a child directory of the
+`docs_dir`. This now raises an error. Additionally, an error is now raised if
+the `docs_dir` is set to the directory which contains your config file rather
+than a child directory. You will need to rearrange you directory structure to
+better conform with the documented [layout].
+
+[layout]: ../user-guide/writing-your-docs/#file-layout
+
 ### Other Changes and Additions to Version 0.16.0
 
 * Bugfix: Support `gh-deploy` command on Windows with Python 3 (#722)
-* Bugfix: Include .woff2 font files in Pyhton package build (#894)
+* Bugfix: Include .woff2 font files in Python package build (#894)
 * Various updates and improvements to Documentation Home Page/Tutorial (#870)
 * Bugfix: Support livereload for config file changes (#735)
 * Bugfix: Non-media template files are no longer copied with media files (#807)
-* Add a flag (-e/--theme-dir) to specifiy theme directory with the commands
+* Add a flag (-e/--theme-dir) to specify theme directory with the commands
   `mkdocs build` and `mkdocs serve` (#832)
-* Fixed issues with Unicode filenames under Windows and Python 2. (#833)
+* Fixed issues with Unicode file names under Windows and Python 2. (#833)
 * Improved the styling of in-line code in the MkDocs theme. (#718)
 * Bugfix: convert variables to JSON when being passed to JavaScript (#850)
 * Updated the ReadTheDocs theme to match the upstream font sizes and colours
diff --git a/mkdocs/config/config_options.py b/mkdocs/config/config_options.py
index b3cb9389..70f610c4 100644
--- a/mkdocs/config/config_options.py
+++ b/mkdocs/config/config_options.py
@@ -229,6 +229,15 @@ class Dir(Type):
 
         return os.path.abspath(value)
 
+    def post_validation(self, config, key_name):
+
+        # Validate that the dir is not the parent dir of the config file.
+        if os.path.dirname(config['config_file_path']) == config[key_name]:
+            raise ValidationError(
+                ("The '{0}' should not be the parent directory of the config "
+                 "file. Use a child directory instead so that the config file "
+                 "is a sibling of the config file.").format(key_name))
+
 
 class SiteDir(Dir):
     """
@@ -239,6 +248,8 @@ class SiteDir(Dir):
 
     def post_validation(self, config, key_name):
 
+        super(SiteDir, self).post_validation(config, key_name)
+
         # Validate that the docs_dir and site_dir don't contain the
         # other as this will lead to copying back and forth on each
         # and eventually make a deep nested mess.
@@ -250,7 +261,7 @@ class SiteDir(Dir):
                  "(site_dir: '{0}', docs_dir: '{1}')"
                  ).format(config['site_dir'], config['docs_dir']))
         elif (config['site_dir'] + os.sep).startswith(config['docs_dir'] + os.sep):
-            self.warnings.append(
+            raise ValidationError(
                 ("The 'site_dir' should not be within the 'docs_dir' as this "
                  "leads to the build directory being copied into itself and "
                  "duplicate nested files in the 'site_dir'."

Ignore the site_dir contents if it is in the docs_dir
We have been telling people to not do this, but it comes up again and again. So I wonder if it is a usecase we should support? I don't really like it. Perhaps we just need to error more strongly and tell users rather than causing obscure problems.
diff --git a/mkdocs/tests/build_tests.py b/mkdocs/tests/build_tests.py
index f6215df2..aead1c85 100644
--- a/mkdocs/tests/build_tests.py
+++ b/mkdocs/tests/build_tests.py
@@ -26,6 +26,8 @@ def load_config(cfg=None):
     cfg = cfg or {}
     if 'site_name' not in cfg:
         cfg['site_name'] = 'Example'
+    if 'config_file_path' not in cfg:
+        cfg['config_file_path'] = os.path.join(os.path.abspath('.'), 'mkdocs.yml')
     conf = config.Config(schema=config.DEFAULT_SCHEMA)
     conf.load_dict(cfg)
 
diff --git a/mkdocs/tests/config/config_options_tests.py b/mkdocs/tests/config/config_options_tests.py
index c492d797..de9396bd 100644
--- a/mkdocs/tests/config/config_options_tests.py
+++ b/mkdocs/tests/config/config_options_tests.py
@@ -186,6 +186,20 @@ class DirTest(unittest.TestCase):
         self.assertRaises(config_options.ValidationError,
                           option.validate, [])
 
+    def test_doc_dir_is_config_dir(self):
+
+        test_config = {
+            'config_file_path': os.path.join(os.path.abspath('.'), 'mkdocs.yml'),
+            'docs_dir': '.'
+        }
+
+        docs_dir = config_options.Dir()
+
+        test_config['docs_dir'] = docs_dir.validate(test_config['docs_dir'])
+
+        self.assertRaises(config_options.ValidationError,
+                          docs_dir.post_validation, test_config, 'docs_dir')
+
 
 class SiteDirTest(unittest.TestCase):
 
@@ -207,12 +221,13 @@ class SiteDirTest(unittest.TestCase):
         )
 
         for test_config in test_configs:
+            test_config['config_file_path'] = j(os.path.abspath('..'), 'mkdocs.yml')
 
             test_config['docs_dir'] = docs_dir.validate(test_config['docs_dir'])
             test_config['site_dir'] = option.validate(test_config['site_dir'])
 
             self.assertRaises(config_options.ValidationError,
-                              option.post_validation, test_config, 'key')
+                              option.post_validation, test_config, 'site_dir')
 
     def test_site_dir_in_docs_dir(self):
 
@@ -225,6 +240,7 @@ class SiteDirTest(unittest.TestCase):
         )
 
         for test_config in test_configs:
+            test_config['config_file_path'] = j(os.path.abspath('..'), 'mkdocs.yml')
 
             docs_dir = config_options.Dir()
             option = config_options.SiteDir()
@@ -232,11 +248,8 @@ class SiteDirTest(unittest.TestCase):
             test_config['docs_dir'] = docs_dir.validate(test_config['docs_dir'])
             test_config['site_dir'] = option.validate(test_config['site_dir'])
 
-            option.post_validation(test_config, 'key')
-            self.assertEqual(len(option.warnings), 1)
-            self.assertEqual(
-                option.warnings[0][:50],
-                "The 'site_dir' should not be within the 'docs_dir'")
+            self.assertRaises(config_options.ValidationError,
+                              option.post_validation, test_config, 'site_dir')
 
 
 class ThemeTest(unittest.TestCase):
diff --git a/mkdocs/tests/config/config_tests.py b/mkdocs/tests/config/config_tests.py
index 04e51de3..497cfa6f 100644
--- a/mkdocs/tests/config/config_tests.py
+++ b/mkdocs/tests/config/config_tests.py
@@ -135,7 +135,8 @@ class ConfigTests(unittest.TestCase):
             conf = config.Config(schema=config.DEFAULT_SCHEMA)
             conf.load_dict({
                 'site_name': 'Example',
-                'docs_dir': tmp_dir
+                'docs_dir': tmp_dir,
+                'config_file_path': os.path.join(os.path.abspath('.'), 'mkdocs.yml')
             })
             conf.validate()
             self.assertEqual(['index.md', 'about.md'], conf['pages'])
@@ -159,7 +160,8 @@ class ConfigTests(unittest.TestCase):
             conf = config.Config(schema=config.DEFAULT_SCHEMA)
             conf.load_dict({
                 'site_name': 'Example',
-                'docs_dir': tmp_dir
+                'docs_dir': tmp_dir,
+                'config_file_path': os.path.join(os.path.abspath('.'), 'mkdocs.yml')
             })
             conf.validate()
             self.assertEqual([
@@ -197,6 +199,7 @@ class ConfigTests(unittest.TestCase):
 
         conf = {
             'site_name': 'Example',
+            'config_file_path': j(os.path.abspath('..'), 'mkdocs.yml')
         }
 
         for test_config in test_configs:

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio mock
apt-get update apt-get install -y gcc
3.9
requirements/project.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
click==8.1.8
coverage==7.8.0
exceptiongroup==1.2.2
execnet==2.1.1
importlib_metadata==8.6.1
iniconfig==2.1.0
Jinja2==3.1.6
livereload==2.7.1
Markdown==3.7
MarkupSafe==3.0.2
-e git+https://github.com/mkdocs/mkdocs.git@c0c4e44cafcc3537b3cb46f5541297b47f707825#egg=mkdocs
mock==5.2.0
packaging==24.2
pluggy==1.5.0
pytest==8.3.5
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-mock==3.14.0
pytest-xdist==3.6.1
PyYAML==6.0.2
tomli==2.2.1
tornado==6.4.2
typing_extensions==4.13.0
zipp==3.21.0

name: mkdocs
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - click==8.1.8
      - coverage==7.8.0
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - jinja2==3.1.6
      - livereload==2.7.1
      - markdown==3.7
      - markupsafe==3.0.2
      - mock==5.2.0
      - packaging==24.2
      - pluggy==1.5.0
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-mock==3.14.0
      - pytest-xdist==3.6.1
      - pyyaml==6.0.2
      - tomli==2.2.1
      - tornado==6.4.2
      - typing-extensions==4.13.0
      - zipp==3.21.0
prefix: /opt/conda/envs/mkdocs

mkdocs/tests/config/config_options_tests.py::DirTest::test_doc_dir_is_config_dir mkdocs/tests/config/config_options_tests.py::SiteDirTest::test_site_dir_in_docs_dir
mkdocs/tests/build_tests.py::BuildTests::test_absolute_link mkdocs/tests/build_tests.py::BuildTests::test_anchor_only_link mkdocs/tests/build_tests.py::BuildTests::test_convert_internal_asbolute_media mkdocs/tests/build_tests.py::BuildTests::test_convert_internal_link mkdocs/tests/build_tests.py::BuildTests::test_convert_internal_link_differing_directory mkdocs/tests/build_tests.py::BuildTests::test_convert_internal_link_with_anchor mkdocs/tests/build_tests.py::BuildTests::test_convert_internal_media mkdocs/tests/build_tests.py::BuildTests::test_convert_markdown mkdocs/tests/build_tests.py::BuildTests::test_convert_multiple_internal_links mkdocs/tests/build_tests.py::BuildTests::test_copy_theme_files mkdocs/tests/build_tests.py::BuildTests::test_copying_media mkdocs/tests/build_tests.py::BuildTests::test_dont_convert_code_block_urls mkdocs/tests/build_tests.py::BuildTests::test_empty_document mkdocs/tests/build_tests.py::BuildTests::test_extension_config mkdocs/tests/build_tests.py::BuildTests::test_extra_context mkdocs/tests/build_tests.py::BuildTests::test_ignore_email_links mkdocs/tests/build_tests.py::BuildTests::test_ignore_external_link mkdocs/tests/build_tests.py::BuildTests::test_markdown_custom_extension mkdocs/tests/build_tests.py::BuildTests::test_markdown_duplicate_custom_extension mkdocs/tests/build_tests.py::BuildTests::test_markdown_fenced_code_extension mkdocs/tests/build_tests.py::BuildTests::test_markdown_table_extension mkdocs/tests/build_tests.py::BuildTests::test_not_use_directory_urls mkdocs/tests/build_tests.py::BuildTests::test_strict_mode_invalid mkdocs/tests/build_tests.py::BuildTests::test_strict_mode_valid mkdocs/tests/config/config_tests.py::ConfigTests::test_config_option mkdocs/tests/config/config_tests.py::ConfigTests::test_default_pages mkdocs/tests/config/config_tests.py::ConfigTests::test_default_pages_nested
mkdocs/tests/config/config_options_tests.py::OptionallyRequiredTest::test_default mkdocs/tests/config/config_options_tests.py::OptionallyRequiredTest::test_empty mkdocs/tests/config/config_options_tests.py::OptionallyRequiredTest::test_replace_default mkdocs/tests/config/config_options_tests.py::OptionallyRequiredTest::test_required mkdocs/tests/config/config_options_tests.py::OptionallyRequiredTest::test_required_no_default mkdocs/tests/config/config_options_tests.py::TypeTest::test_length mkdocs/tests/config/config_options_tests.py::TypeTest::test_multiple_types mkdocs/tests/config/config_options_tests.py::TypeTest::test_single_type mkdocs/tests/config/config_options_tests.py::URLTest::test_invalid mkdocs/tests/config/config_options_tests.py::URLTest::test_invalid_url mkdocs/tests/config/config_options_tests.py::URLTest::test_valid_url mkdocs/tests/config/config_options_tests.py::RepoURLTest::test_edit_uri_bitbucket mkdocs/tests/config/config_options_tests.py::RepoURLTest::test_edit_uri_custom mkdocs/tests/config/config_options_tests.py::RepoURLTest::test_edit_uri_github mkdocs/tests/config/config_options_tests.py::RepoURLTest::test_repo_name_bitbucket mkdocs/tests/config/config_options_tests.py::RepoURLTest::test_repo_name_custom mkdocs/tests/config/config_options_tests.py::RepoURLTest::test_repo_name_github mkdocs/tests/config/config_options_tests.py::DirTest::test_file mkdocs/tests/config/config_options_tests.py::DirTest::test_incorrect_type_attribute_error mkdocs/tests/config/config_options_tests.py::DirTest::test_incorrect_type_type_error mkdocs/tests/config/config_options_tests.py::DirTest::test_missing_dir mkdocs/tests/config/config_options_tests.py::DirTest::test_missing_dir_but_required mkdocs/tests/config/config_options_tests.py::DirTest::test_valid_dir mkdocs/tests/config/config_options_tests.py::SiteDirTest::test_doc_dir_in_site_dir mkdocs/tests/config/config_options_tests.py::ThemeTest::test_theme mkdocs/tests/config/config_options_tests.py::ThemeTest::test_theme_invalid mkdocs/tests/config/config_options_tests.py::ExtrasTest::test_empty mkdocs/tests/config/config_options_tests.py::ExtrasTest::test_invalid mkdocs/tests/config/config_options_tests.py::ExtrasTest::test_provided mkdocs/tests/config/config_options_tests.py::ExtrasTest::test_talk mkdocs/tests/config/config_options_tests.py::PagesTest::test_invalid_config mkdocs/tests/config/config_options_tests.py::PagesTest::test_invalid_type mkdocs/tests/config/config_options_tests.py::PagesTest::test_provided mkdocs/tests/config/config_options_tests.py::PagesTest::test_provided_dict mkdocs/tests/config/config_options_tests.py::PagesTest::test_provided_empty mkdocs/tests/config/config_options_tests.py::NumPagesTest::test_invalid_pages mkdocs/tests/config/config_options_tests.py::NumPagesTest::test_many_pages mkdocs/tests/config/config_options_tests.py::NumPagesTest::test_one_page mkdocs/tests/config/config_options_tests.py::NumPagesTest::test_provided mkdocs/tests/config/config_options_tests.py::PrivateTest::test_defined mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_builtins mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_builtins_config mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_configkey mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_duplicates mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_invalid_config_item mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_invalid_config_option mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_invalid_dict_item mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_list_dicts mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_mixed_list mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_none mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_not_list mkdocs/tests/config/config_options_tests.py::MarkdownExtensionsTest::test_simple_list mkdocs/tests/config/config_tests.py::ConfigTests::test_doc_dir_in_site_dir mkdocs/tests/config/config_tests.py::ConfigTests::test_empty_config mkdocs/tests/config/config_tests.py::ConfigTests::test_invalid_config mkdocs/tests/config/config_tests.py::ConfigTests::test_missing_config_file mkdocs/tests/config/config_tests.py::ConfigTests::test_missing_site_name mkdocs/tests/config/config_tests.py::ConfigTests::test_nonexistant_config mkdocs/tests/config/config_tests.py::ConfigTests::test_theme
docs/about/release-notes.md mkdocs/config/config_options.py
docs/about/release-notes.md mkdocs/config/config_options.py