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

  1. Rename labels inside nested mosaics so every label is globally unique
  2. After creation, remap the returned dict to whatever names your code needs
  3. 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

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


AI-assisted analysis of matplotlib/matplotlib@b379c1b69e (2026-08-21). Data as JSON: /api/errors/6dbc070c26481756. Report an issue: GitHub.