matplotlib/matplotlib · error · ValueError
There are duplicate keys {overlap} between the outer layout
Error message
There are duplicate keys {overlap} between the outer layout
{mosaic!r}
and the nested layout
{nested_mosaic} What it means
Nested sub-mosaics are flattened into the single dict that subplot_mosaic returns. If a label is used both in the outer layout and inside a nested layout, the keys collide in that flat dict, so _do_layout raises this ValueError listing the overlapping labels (lib/matplotlib/figure.py:2266).
Source
Thrown at lib/matplotlib/figure.py:2266
'label': str(name),
**subplot_kw,
**per_subplot_kw.get(name, {})
}
)
output[name] = ax
elif method == 'nested':
nested_mosaic = arg
j, k = key
# recursively add the nested mosaic
rows, cols = nested_mosaic.shape
nested_output = _do_layout(
gs[j, k].subgridspec(rows, cols),
nested_mosaic,
*_identify_keys_and_nested(nested_mosaic)
)
overlap = set(output) & set(nested_output)
if overlap:
raise ValueError(
f"There are duplicate keys {overlap} "
f"between the outer layout\n{mosaic!r}\n"
f"and the nested layout\n{nested_mosaic}"
)
output.update(nested_output)
else:
raise RuntimeError("This should never happen")
return output
mosaic = _make_array(mosaic)
rows, cols = mosaic.shape
gs = self.add_gridspec(rows, cols, **gridspec_kw)
ret = _do_layout(gs, mosaic, *_identify_keys_and_nested(mosaic))
ax0 = next(iter(ret.values()))
for ax in ret.values():
if sharex:
ax.sharex(ax0)
ax._label_outer_xaxis(skip_non_rectangular_axes=True)View on GitHub (pinned to b379c1b69e)
Solutions
- Rename labels inside nested mosaics so every label is globally unique
- After creation, remap the returned dict to whatever names your code needs
- When generating nested layouts, prefix nested labels with their position or path
Example fix
// before fig.subplot_mosaic([['a', [['a', 'b'], ['c', 'd']]]]) // after fig.subplot_mosaic([['a', [['x', 'b'], ['c', 'd']]]])
Defensive patterns
Strategy: validation
Validate before calling
def nested_labels_unique(mosaic):
top, nested = set(), set()
def walk(m, depth):
for row in m:
for v in row:
if isinstance(v, (list, tuple)):
walk(v, depth + 1)
elif v != '.':
(top if depth == 0 else nested).add(v)
walk(mosaic, 0)
return not (top & nested) Prevention
- Prefix nested labels (e.g. 'tl_a') to keep them globally unique
- When composing mosaics from helpers, pass a label prefix to each helper
When it happens
Trigger: fig.subplot_mosaic([['a', [['a', 'b'], ['c', 'd']]]]) — outer 'a' also appears inside the nested grid; nested layouts generated with generic names like 'plot' or 'cax' that repeat outer names.
Common situations: Copying nested layout templates that reuse common label names; composing layouts from helper functions that each use their own fixed labels; refactoring a flat mosaic into nested sub-layouts without renaming.
Related errors
- The key {sub_key!r} appears multiple times.
- The key {k!r} appears multiple times.
- There are duplicate keys {name} in the layout {mosaic!r}
- List mosaic specification must be 2D
- All of the rows must be the same length, however the first r
AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21).
Data as JSON: /api/errors/6dbc070c26481756.
Report an issue: GitHub.