{"record":{"id":"9fd99e23c55433e6","repo":"matplotlib/matplotlib","slug":"grab-frame-got-an-unexpected-keyword-argument-k-r","errorCode":null,"errorMessage":"grab_frame got an unexpected keyword argument {k!r}","messagePattern":"grab_frame got an unexpected keyword argument (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/matplotlib/animation.py","lineNumber":1835,"sourceCode":"                if not isinstance(i, mpl.artist.Artist):\n                    raise err\n\n            self._drawn_artists = sorted(self._drawn_artists,\n                                         key=lambda x: x.get_zorder())\n\n            for a in self._drawn_artists:\n                a.set_animated(self._blit)\n\n\ndef _validate_grabframe_kwargs(savefig_kwargs):\n    if mpl.rcParams['savefig.bbox'] == 'tight':\n        raise ValueError(\n            f\"{mpl.rcParams['savefig.bbox']=} must not be 'tight' as it \"\n            \"may cause frame size to vary, which is inappropriate for animation.\"\n        )\n    for k in ('dpi', 'bbox_inches', 'format'):\n        if k in savefig_kwargs:\n            raise TypeError(\n                f\"grab_frame got an unexpected keyword argument {k!r}\"\n            )\n","sourceCodeStart":1817,"sourceCodeEnd":1838,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/animation.py#L1817-L1838","documentation":"grab_frame ultimately calls fig.savefig(**savefig_kwargs) after _validate_grabframe_kwargs strips the writer's own controls. The keys 'dpi', 'bbox_inches' and 'format' are managed by the writer (dpi comes from the figure, bbox must not be tight per error 69, format is writer.frame_format), so passing any of them via savefig_kwargs raises TypeError 'grab_frame got an unexpected keyword argument {k!r}'.","triggerScenarios":"anim.save('out.mp4', savefig_kwargs={'dpi': 72}); anim.save('out.mp4', savefig_kwargs={'bbox_inches': 'tight'}); anim.save('out.gif', savefig_kwargs={'format': 'png'}); calling writer.grab_frame(dpi=...) directly.","commonSituations":"Copy-pasting savefig kwargs from static-export code into anim.save; trying to control output resolution per-save; generic export wrappers that forward one kwargs dict to both plt.savefig and anim.save.","solutions":["Control resolution via the figure: fig.set_dpi(72) (or pass dpi when creating the figure / to the writer where supported) before anim.save","Remove dpi/bbox_inches/format from savefig_kwargs; pass only genuinely pass-through kwargs like facecolor or transparent","Set writer.frame_format (e.g. PillowWriter(frame_format='png')) instead of 'format'","Handle bbox via layout engines (layout='constrained') or post-crop the video"],"exampleFix":"# before\nanim.save(\"out.mp4\", savefig_kwargs={\"dpi\": 72})  # TypeError\n\n# after\nfig.set_dpi(72)\nanim.save(\"out.mp4\")","handlingStrategy":"validation","validationCode":"WRITER_OWNED = {\"dpi\", \"bbox_inches\", \"format\"}\n\ndef safe_grabframe_kwargs(savefig_kwargs):\n    bad = WRITER_OWNED & set(savefig_kwargs)\n    if bad:\n        raise TypeError(f\"keys {sorted(bad)} are controlled by the writer/figure, \"\n                        f\"got them in savefig_kwargs\")\n    return savefig_kwargs","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set resolution once via fig.set_dpi / dpi= at figure creation","Keep static-savefig kwargs and animation savefig_kwargs in separate dicts","Read MovieWriter.grab_frame docs before forwarding generic kwargs"],"tags":["animation","savefig","kwargs","dpi","movie-writer"],"backgroundTag":"unsupported-kwarg","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}