Description
toon-python (0.9.0b1) mishandles nested array-of-array values in both directions. The reference implementation @toon-format/toon (v2.3.0) round-trips [[[]]] correctly, so both facets are specific to toon-python.
Encode: encode([[[]]]) produces a list-array header ([1]:) that claims one item over a body that yields none, so it cannot be decoded — even by toon-python's own decoder. encode([[[]]]) produces:
decode() of that raises:
File ".../toon_format/decoder.py", line 786, in decode_list_array
raise ToonDecodeError(f"Expected {expected_length} items, but got {len(result)}")
toon_format.decoder.ToonDecodeError: Expected 1 items, but got 0
Decode: decoding the reference (TypeScript) encoding of [[[]]] returns an object instead of an array — the internal list-array markers leak out as keys:
The decoder facet is not specific to empty arrays; any nesting depth >= 3 reproduces it (e.g. the reference encoding of [[{"s":"a:b"}]] decodes to [{"[1]": {}, "- s": "a:b"}]).
Boundary (reduced with a differential fuzzer + delta-shrinker):
[] — fine
[[]] — fine
[[[]]] — breaks (minimal reproducer)
Environment:
toon-python (toon_format): 0.9.0b1
reference impl @toon-format/toon: v2.3.0 (round-trips this input correctly)
Python: 3.14
Reproduction Steps
- from toon_format import encode, decode
- Call encode([[[]]]) — produces:
[1]:
[1]:
- [0]:
- Call decode() on that output — raises ToonDecodeError: Expected 1 items, but got 0
(toon-python cannot decode its own encoding)
Separately, decoding the reference @toon-format/toon encoding of [[[]]] returns
[{"[1]": {}, "-": []}] — a nested array decoded as an object.
Expected Behavior
[[[]]] round-trips unchanged: decode(encode([[[]]])) == [[[]]].
(The reference impl @toon-format/toon does this correctly.)
Actual Behavior
encode([[[]]]) produces:
The outer header says [1]: (one item) but the innermost level is [0]: (zero items).
decode() of that raises:
File ".../toon_format/decoder.py", line 786, in decode_list_array
raise ToonDecodeError(f"Expected {expected_length} items, but got {len(result)}")
toon_format.decoder.ToonDecodeError: Expected 1 items, but got 0
Separately, decoding the reference @toon-format/toon encoding of [[[]]] returns an
object instead of an array:
Environment
toon-python (toon_format): 0.9.0b1
reference impl @toon-format/toon: v2.3.0 (round-trips this input correctly)
Python: 3.14
Additional Context
The decoder facet is not specific to empty arrays; any nesting depth >= 3 reproduces it
(e.g. the reference encoding of [[{"s":"a:b"}]] decodes to [{"[1]": {}, "- s": "a:b"}]).
Boundary, reduced with a differential fuzzer + delta-shrinker:
[] — fine
[[]] — fine
[[[]]] — breaks (minimal reproducer)
Description
toon-python (0.9.0b1) mishandles nested array-of-array values in both directions. The reference implementation @toon-format/toon (v2.3.0) round-trips [[[]]] correctly, so both facets are specific to toon-python.
Encode: encode([[[]]]) produces a list-array header ([1]:) that claims one item over a body that yields none, so it cannot be decoded — even by toon-python's own decoder. encode([[[]]]) produces:
decode() of that raises:
Decode: decoding the reference (TypeScript) encoding of [[[]]] returns an object instead of an array — the internal list-array markers leak out as keys:
The decoder facet is not specific to empty arrays; any nesting depth >= 3 reproduces it (e.g. the reference encoding of [[{"s":"a:b"}]] decodes to [{"[1]": {}, "- s": "a:b"}]).
Boundary (reduced with a differential fuzzer + delta-shrinker):
[] — fine
[[]] — fine
[[[]]] — breaks (minimal reproducer)
Environment:
toon-python (toon_format): 0.9.0b1
reference impl @toon-format/toon: v2.3.0 (round-trips this input correctly)
Python: 3.14
Reproduction Steps
[1]:
[1]:
- [0]:
(toon-python cannot decode its own encoding)
Separately, decoding the reference @toon-format/toon encoding of [[[]]] returns
[{"[1]": {}, "-": []}] — a nested array decoded as an object.
Expected Behavior
[[[]]] round-trips unchanged: decode(encode([[[]]])) == [[[]]].
(The reference impl @toon-format/toon does this correctly.)
Actual Behavior
encode([[[]]]) produces:
The outer header says [1]: (one item) but the innermost level is [0]: (zero items).
decode() of that raises:
Separately, decoding the reference @toon-format/toon encoding of [[[]]] returns an
object instead of an array:
Environment
toon-python (toon_format): 0.9.0b1
reference impl @toon-format/toon: v2.3.0 (round-trips this input correctly)
Python: 3.14
Additional Context
The decoder facet is not specific to empty arrays; any nesting depth >= 3 reproduces it
(e.g. the reference encoding of [[{"s":"a:b"}]] decodes to [{"[1]": {}, "- s": "a:b"}]).
Boundary, reduced with a differential fuzzer + delta-shrinker:
[] — fine
[[]] — fine
[[[]]] — breaks (minimal reproducer)