Regression in 0.15.1: valid out-of-order child table raises KeyAlreadyPresent
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 68/100
Research direction
Start by running the minimal reproduction and inspect _validate_table_candidate() together with the OutOfOrderTableProxy and Table validation described in the report. The fix is done when the document parses successfully without KeyAlreadyPresent, while the listed older-version behavior and expected nested result remain valid.
Written by the indexing model from the issue text.
Description
Summary
Tomlkit 0.15.1 rejects a valid document when a table contains an out-of-order
child, its concrete parent is declared afterward, and another table separates a
later sibling child.
This is a regression: tomllib and Tomlkit 0.13.3, 0.14.0, and 0.15.0 all
accept the document.
Minimal reproduction
import tomlkit
source = """\
[tool.ruff]
[tool.ruff.lint.a]
[tool.ruff.lint]
[[tool.poetry.source]]
[tool.ruff.lint.b]
"""
tomlkit.loads(source)
Actual result
tomlkit.exceptions.ParseError: Key "lint" already exists. at line 5 col 0
Expected result
The document parses successfully, matching tomllib:
{
"tool": {
"ruff": {"lint": {"a": {}, "b": {}}},
"poetry": {"source": [{}]},
}
}
Each header in the minimized example is necessary to trigger the failure. The
array-of-tables is not special: replacing [[tool.poetry.source]] with any
intervening table header also reproduces it, while removing the intervening
header makes it pass.
Regression boundary
Reproduced on Python 3.13.8 and 3.14.2:
- stdlib
tomllib: passes - Tomlkit 0.13.3: passes
- Tomlkit 0.14.0: passes
- Tomlkit 0.15.0: passes
- Tomlkit 0.15.1 and current
master: fail
Suspected root cause
The regression appears to come from the concrete+super validation added in
#530 / commit d3c76f0.
When [tool.ruff.lint.b] is appended, the existing lint entry is represented
by OutOfOrderTableProxy, while the candidate is a Table.
_validate_table_candidate() checks:
isinstance(existing, (Table, AoT)) != isinstance(v, (Table, AoT))
The proxy is table-like but fails the left-hand isinstance check, so valid
input is reported as a type conflict and raises KeyAlreadyPresent("lint").
- Dominant language
- Python
- Stars
- 850
- Forks
- 163
- Avg merge
- 13m
- Merged PRs (30d)
- 2
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from python-poetry/tomlkit
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
python-poetry/tomlkit#546 · 2 comments ·
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
python-poetry/tomlkit#603 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 52/100
python-poetry/tomlkit#580 · 1 comment ·
-
Difficulty 3/5 1-2 days Newbie friendliness 72/100
python-poetry/tomlkit#577 ·
-
Difficulty 5/5 Over a week Newbie friendliness 20/100
python-poetry/tomlkit#574 · 5 comments ·
All issues in python-poetry/tomlkit
Similar issues
-
Add: hunch Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
AbdelStark/awesome-typesafe#104 ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
DiamondLightSource/dodal#2211 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
openml/openml-python#1749 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
sipyourdrink-ltd/bernstein#6191 ·