{"record":{"id":"a0c4630116f5af7a","repo":"matplotlib/matplotlib","slug":"total-and-sep-cannot-both-be-none-when-using-layou","errorCode":null,"errorMessage":"total and sep cannot both be None when using layout mode 'equal'","messagePattern":"total and sep cannot both be None when using layout mode 'equal'","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/matplotlib/offsetbox.py","lineNumber":142,"sourceCode":"\n    elif mode == \"expand\":\n        # This is a bit of a hack to avoid a TypeError when *total*\n        # is None and used in conjugation with tight layout.\n        if total is None:\n            total = 1\n        if len(widths) > 1:\n            sep = (total - sum(widths)) / (len(widths) - 1)\n        else:\n            sep = 0\n        offsets_ = np.cumsum([0] + [w + sep for w in widths])\n        offsets = offsets_[:-1]\n        return total, offsets\n\n    elif mode == \"equal\":\n        maxh = max(widths)\n        if total is None:\n            if sep is None:\n                raise ValueError(\"total and sep cannot both be None when \"\n                                 \"using layout mode 'equal'\")\n            total = (maxh + sep) * len(widths)\n        else:\n            sep = total / len(widths) - maxh\n        offsets = (maxh + sep) * np.arange(len(widths))\n        return total, offsets\n\n\ndef _get_aligned_offsets(yspans, height, align=\"baseline\"):\n    \"\"\"\n    Align boxes each specified by their ``(y0, y1)`` spans.\n\n    For simplicity of the description, the terminology used here assumes a\n    horizontal layout (i.e., vertical alignment), but the function works\n    equally for a vertical layout.\n\n    Parameters\n    ----------","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/offsetbox.py#L124-L160","documentation":"offsetbox._get_packed_offsets, the layout engine used by HPacker/VPacker (and everything built on them, like AnnotationBbox legends), distributes children according to mode. In mode='equal' every child gets an equal slice of the available space; the total slice size is derived either from the packer's fixed width/height ('total') or from the per-item gap 'sep'. When both total and sep are None the spacing is underdetermined, so it raises ValueError(\"total and sep cannot both be None when using layout mode 'equal'\").","triggerScenarios":"HPacker(children=[...], mode='equal', width=None, sep=None) or VPacker(mode='equal', height=None, sep=None); subclasses of PackerBase that forward None width/sep with mode='equal'; drawing (savefig/show) triggers _get_bbox_and_child_offsets, where the error surfaces at draw time.","commonSituations":"Migrating layouts that used mode='fixed' to 'equal' and passing sep=None to 'let it auto-size'; constructing custom OffsetBox toolbars/legends where the container size is only known later; the error appearing only at render time, confusing the stack trace.","solutions":["Give the packer an explicit size: HPacker(..., width=300, mode='equal') (width/height are in pixels).","Or give an explicit separator: HPacker(..., sep=5, mode='equal') (sep in points).","If you want auto-sized tight packing, use the default mode='fixed' instead of 'equal'.","Note the error fires at draw time — fix the constructor arguments in the traceback's packer creation frame, not where savefig appears."],"exampleFix":"# before\nbox = offsetbox.HPacker(children=[a, b], mode='equal', sep=None, width=None)\n\n# after\nbox = offsetbox.HPacker(children=[a, b], mode='equal', width=200)","handlingStrategy":"validation","validationCode":"def make_hpacker(children, mode='equal', width=None, sep=None):\n    if mode == 'equal' and width is None and sep is None:\n        sep = 5  # or raise with a clear message naming the packer\n    return offsetbox.HPacker(children=children, mode=mode, width=width, sep=sep)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["With mode='equal', always pass an explicit width (HPacker) / height (VPacker) or sep.","Remember the error surfaces at draw time; set a breakpoint on the packer constructor, not on savefig.","Use mode='fixed' for auto-sized tight packing."],"tags":["matplotlib","offsetbox","hpacker","vpacker","layout"],"backgroundTag":"missing-required-parameter","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}