Read only [tool.codespell] from TOML config (#3975)
diff --git a/codespell_lib/_codespell.py b/codespell_lib/_codespell.py
index 8ebb19d..994c5c4 100644
--- a/codespell_lib/_codespell.py
+++ b/codespell_lib/_codespell.py
@@ -712,10 +712,12 @@
         if tomllib is not None:
             for toml_file in toml_files:
                 with open(toml_file, "rb") as f:
-                    data = tomllib.load(f).get("tool", {})
-                if "codespell" in data:
-                    data["codespell"] = _toml_to_parseconfig(data["codespell"])
-                config.read_dict(data)
+                    data = tomllib.load(f).get("tool", {}).get("codespell")
+                if data is not None:
+                    if not isinstance(data, dict):
+                        msg = f"{toml_file}: [tool.codespell] must be a table"
+                        raise configparser.Error(msg)
+                    config.read_dict({"codespell": _toml_to_parseconfig(data)})
 
     # Collect which config files are going to be used
     used_cfg_files = []
diff --git a/codespell_lib/tests/test_basic.py b/codespell_lib/tests/test_basic.py
index d1c66a1..930f09f 100644
--- a/codespell_lib/tests/test_basic.py
+++ b/codespell_lib/tests/test_basic.py
@@ -1428,7 +1428,10 @@
     assert "ill-formed config file" in stderr
 
 
-@pytest.mark.parametrize("kind", ["cfg", "cfg_multiline", "toml", "toml_list"])
+@pytest.mark.parametrize(
+    "kind",
+    ["cfg", "cfg_multiline", "toml", "toml_list", "toml_sibling_array"],
+)
 def test_config_toml(
     tmp_path: Path,
     capsys: pytest.CaptureFixture[str],
@@ -1482,14 +1485,24 @@
 check-filenames = false
 count = true
 """
-        else:
-            assert kind == "toml_list"
+        elif kind == "toml_list":
             text = """\
 [tool.codespell]
 skip = ['bad.txt', 'whatever.txt']
 check-filenames = false
 count = true
 """
+        else:
+            assert kind == "toml_sibling_array"
+            text = """\
+[tool.codespell]
+skip = 'bad.txt,whatever.txt'
+check-filenames = false
+count = true
+
+[[tool.dynamic-metadata]]
+provider = 'scikit_build_core.metadata.version'
+"""
         tomlfile.write_text(text)
 
     # Should pass when skipping bad.txt or abandonned.txt
@@ -1514,6 +1527,22 @@
     assert "abandonned.txt" not in stdout
 
 
+def test_config_toml_codespell_array(
+    tmp_path: Path,
+    capsys: pytest.CaptureFixture[str],
+) -> None:
+    if sys.version_info < (3, 11):
+        pytest.importorskip("tomli")
+    tomlfile = tmp_path / "pyproject.toml"
+    tomlfile.write_text("[[tool.codespell]]\nskip = 'bad.txt'\n")
+
+    result = cs.main("--toml", tomlfile, std=True)
+    assert isinstance(result, tuple)
+    code, _, stderr = result
+    assert code == EX_CONFIG
+    assert "[tool.codespell] must be a table" in stderr
+
+
 @contextlib.contextmanager
 def FakeStdin(text: str) -> Generator[None, None, None]:
     oldin = sys.stdin