Description
tomlkit.parse() accepts a TOML document, but later accessing a parsed table with doc.get("hooks") can raise:
tomlkit.exceptions.KeyAlreadyPresent: Key "Stop" already exists.
This happened with a valid TOML config that contains repeated array tables such as [[hooks.Stop]] plus sibling/subtables under [hooks].
The failure appears to happen while constructing an OutOfOrderTableProxy, not during parsing.
Observed behavior
This code path fails:
import tomlkit
from pathlib import Path
text = Path("config.toml").read_text(encoding="utf-8")
doc = tomlkit.parse(text) # succeeds
hooks = doc.get("hooks") # raises KeyAlreadyPresent
Traceback:
Traceback (most recent call last):
File "<string>", line 11, in <module>
File "<frozen _collections_abc>", line 807, in get
File ".../tomlkit/container.py", line 711, in __getitem__
item = self.item(key)
File ".../tomlkit/container.py", line 517, in item
return OutOfOrderTableProxy(self, idx)
File ".../tomlkit/container.py", line 912, in __init__
self._internal_container._raw_append(k, v)
File ".../tomlkit/container.py", line 360, in _raw_append
raise KeyAlreadyPresent(key)
tomlkit.exceptions.KeyAlreadyPresent: Key "Stop" already exists.
Expected behavior
If tomlkit.parse() accepts the TOML document, then accessing doc.get("hooks") should not fail with KeyAlreadyPresent.
Repeated array tables like this are valid TOML:
[hooks]
[[hooks.Stop]]
matcher = ".*"
[[hooks.Stop.hooks]]
type = "command"
command = "one"
# even some actual content in here is valid but tomlkit gives an issue if something else is present
[[hooks.Stop]]
matcher = ".*"
[[hooks.Stop.hooks]]
type = "command"
command = "two"
[hooks.state]
[hooks.state.example]
trusted_hash = "sha256:abc"
Actual behavior
On the original config, tomlkit.parse(text) succeeded, but doc.get("hooks") raised KeyAlreadyPresent: Key "Stop" already exists.
Versions tested
This reproduces with:
Python 3.12.7
tomlkit 0.14.0
tomlkit 0.15.0
tomlkit 0.15.0 produced the same class of traceback:
0.15.0
tomlkit.exceptions.KeyAlreadyPresent: Key "Stop" already exists.
Notes
The issue seems related to OutOfOrderTableProxy handling repeated array tables under a table that also contains sibling tables/subtables. Reordering the TOML so repeated [[hooks.Stop]] entries are grouped before other sibling tables avoids the failure in my application, but the original TOML should still be accessible after parsing.
Description
tomlkit.parse()accepts a TOML document, but later accessing a parsed table withdoc.get("hooks")can raise:This happened with a valid TOML config that contains repeated array tables such as [[hooks.Stop]] plus sibling/subtables under [hooks].
The failure appears to happen while constructing an OutOfOrderTableProxy, not during parsing.
Observed behavior
This code path fails:
Traceback:
Expected behavior
If tomlkit.parse() accepts the TOML document, then accessing doc.get("hooks") should not fail with KeyAlreadyPresent.
Repeated array tables like this are valid TOML:
Actual behavior
On the original config, tomlkit.parse(text) succeeded, but doc.get("hooks") raised KeyAlreadyPresent: Key "Stop" already exists.
Versions tested
This reproduces with:
Notes
The issue seems related to
OutOfOrderTableProxyhandling repeated array tables under a table that also contains sibling tables/subtables. Reordering the TOML so repeated [[hooks.Stop]] entries are grouped before other sibling tables avoids the failure in my application, but the original TOML should still be accessible after parsing.