René's URL Explorer Experiment


Title: [BUG] Warn when legend() receives mismatched handles and labels in 2-argument positional form by EncryptedDoom · Pull Request #31315 · matplotlib/matplotlib · GitHub

Open Graph Title: [BUG] Warn when legend() receives mismatched handles and labels in 2-argument positional form by EncryptedDoom · Pull Request #31315 · matplotlib/matplotlib

X Title: [BUG] Warn when legend() receives mismatched handles and labels in 2-argument positional form by EncryptedDoom · Pull Request #31315 · matplotlib/matplotlib

Description: PR Summary Closes #24050 Why is this change necessary? When calling ax.legend() using the 2-argument positional form — ax.legend(handles, labels) — with mismatched list lengths, matplotlib silently truncates to the shorter list with no warning raised to the user. This is a silent data loss scenario: the user gets a legend that is missing entries with no indication that anything went wrong. What problem does it solve? A warning already exists in _parse_legend_args() for the keyword argument path (ax.legend(handles=..., labels=...)), implemented at lines 1329–1334: if (hasattr(handles, "__len__") and hasattr(labels, "__len__") and len(handles) != len(labels)): _api.warn_external(f"Mismatched number of handles and labels: ...") However, the 2-argument positional path (elif len(args) == 2) at line 1365 had no equivalent check: elif len(args) == 2: handles, labels = args[:2] # No mismatch check — silent truncation This PR brings the positional path to parity with the keyword path by adding the same mismatch check. What is the reasoning for this implementation? The fix uses _api.warn_external() — consistent with the existing warning convention in this function — which correctly sets the stacklevel so the warning points to the user's legend() call site rather than to internal matplotlib code. No API changes are introduced. The behaviour after the warning is unchanged — matplotlib still truncates to the shorter list, preserving backward compatibility. Minimum self-contained example Before this fix (no warning raised): import matplotlib.pyplot as plt fig, ax = plt.subplots() line1, = ax.plot([1, 2], label='A') line2, = ax.plot([3, 4], label='B') # 2 handles, 1 label — silently drops line2 from legend ax.legend([line1, line2], ['only_one_label']) plt.show() After this fix: UserWarning: Mismatched number of handles and labels: len(handles) = 2 len(labels) = 1 AI Disclosure This contribution was developed with assistance from Claude (Anthropic) for identifying the bug location within the codebase and structuring the fix. The actual code changes, testing, and verification were performed by me. Claude was used as a reference tool to navigate the codebase, consistent with how one might use documentation or a senior developer for guidance. PR Checklist Closes #24050 is in the body of the PR description New and changed code is tested — test_legend_mismatched_positional_args() added in lib/matplotlib/tests/test_legend.py [N/A] Plotting related features demonstrated in an example — this is a bug fix (warning addition), not a new plotting feature [N/A] New Features and API Changes noted with directive — no API change introduced; behaviour is unchanged, only a warning is added Documentation complies with general and docstring guidelines — no new public API or docstring added; existing docstring already states "If they are not, they are truncated to the length of the shorter list" which remains accurate

Open Graph Description: PR Summary Closes #24050 Why is this change necessary? When calling ax.legend() using the 2-argument positional form — ax.legend(handles, labels) — with mismatched list lengths, matplotlib silently...

X Description: PR Summary Closes #24050 Why is this change necessary? When calling ax.legend() using the 2-argument positional form — ax.legend(handles, labels) — with mismatched list lengths, matplotlib silently...

Opengraph URL: https://github.com/matplotlib/matplotlib/pull/31315

X: @github

direct link

Domain: github.com

route-pattern/:user_id/:repository/pull/:id/files(.:format)
route-controllerpull_requests
route-actionfiles
fetch-noncev2:cdf02e93-a701-c6bd-ae2d-c47f564fd5d5
current-catalog-service-hashae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b
request-idD194:1ED861:76E530:9C9F78:6A530AA8
html-safe-nonceeb32b954709b110a8d612e119cb65bc1d943d2de27c6642079023b49bbdf9ebb
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEMTk0OjFFRDg2MTo3NkU1MzA6OUM5Rjc4OjZBNTMwQUE4IiwidmlzaXRvcl9pZCI6IjYzNDgxMzQzMTQzNjcxOTE3MjAiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmacdcf38c8e1eccc4e59a11673c2150f788b94b1615f6465d11fb6b1bd9c3a6c129
hovercard-subject-tagpull_request:3404611643
github-keyboard-shortcutsrepository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///pull_requests/show/files
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/matplotlib/matplotlib/pull/31315/files
twitter:imagehttps://avatars.githubusercontent.com/u/76607058?s=400&v=4
twitter:cardsummary_large_image
og:imagehttps://avatars.githubusercontent.com/u/76607058?s=400&v=4
og:image:altPR Summary Closes #24050 Why is this change necessary? When calling ax.legend() using the 2-argument positional form — ax.legend(handles, labels) — with mismatched list lengths, matplotlib silently...
og:site_nameGitHub
og:typeobject
hostnamegithub.com
expected-hostnamegithub.com
Noneb9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb
turbo-cache-controlno-preview
diff-viewunified
go-importgithub.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git
octolytics-dimension-user_id215947
octolytics-dimension-user_loginmatplotlib
octolytics-dimension-repository_id1385122
octolytics-dimension-repository_nwomatplotlib/matplotlib
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id1385122
octolytics-dimension-repository_network_root_nwomatplotlib/matplotlib
turbo-body-classeslogged-out env-production page-responsive full-width
disable-turbotrue
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release07a982c1d40157c619b364352b704c3ce66bb332
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/matplotlib/matplotlib/pull/31315/files#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmatplotlib%2Fmatplotlib%2Fpull%2F31315%2Ffiles
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fmatplotlib%2Fmatplotlib%2Fpull%2F31315%2Ffiles
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fpull_requests%2Fshow%2Ffiles&source=header-repo&source_repo=matplotlib%2Fmatplotlib
Reloadhttps://github.com/matplotlib/matplotlib/pull/31315/files
Reloadhttps://github.com/matplotlib/matplotlib/pull/31315/files
Reloadhttps://github.com/matplotlib/matplotlib/pull/31315/files
Please reload this pagehttps://github.com/matplotlib/matplotlib/pull/31315/files
matplotlib https://github.com/matplotlib
matplotlibhttps://github.com/matplotlib/matplotlib
Please reload this pagehttps://github.com/matplotlib/matplotlib/pull/31315/files
Notifications https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Fork 8.4k https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Star 23k https://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib
Code https://github.com/matplotlib/matplotlib
Issues 1.1k https://github.com/matplotlib/matplotlib/issues
Pull requests 408 https://github.com/matplotlib/matplotlib/pulls
Actions https://github.com/matplotlib/matplotlib/actions
Projects https://github.com/matplotlib/matplotlib/projects
Wiki https://github.com/matplotlib/matplotlib/wiki
Security and quality 0 https://github.com/matplotlib/matplotlib/security
Insights https://github.com/matplotlib/matplotlib/pulse
Code https://github.com/matplotlib/matplotlib
Issues https://github.com/matplotlib/matplotlib/issues
Pull requests https://github.com/matplotlib/matplotlib/pulls
Actions https://github.com/matplotlib/matplotlib/actions
Projects https://github.com/matplotlib/matplotlib/projects
Wiki https://github.com/matplotlib/matplotlib/wiki
Security and quality https://github.com/matplotlib/matplotlib/security
Insights https://github.com/matplotlib/matplotlib/pulse
Sign up for GitHub https://github.com/signup?return_to=%2Fmatplotlib%2Fmatplotlib%2Fissues%2Fnew%2Fchoose
terms of servicehttps://docs.github.com/terms
privacy statementhttps://docs.github.com/privacy
Sign inhttps://github.com/login?return_to=%2Fmatplotlib%2Fmatplotlib%2Fissues%2Fnew%2Fchoose
rcomerhttps://github.com/rcomer
matplotlib:mainhttps://github.com/matplotlib/matplotlib/tree/main
Conversation 13 https://github.com/matplotlib/matplotlib/pull/31315
Commits 15 https://github.com/matplotlib/matplotlib/pull/31315/commits
Checks 37 https://github.com/matplotlib/matplotlib/pull/31315/checks
Files changed 2 https://github.com/matplotlib/matplotlib/pull/31315/files
[BUG] Warn when legend() receives mismatched handles and labels in 2-argument positional form https://github.com/matplotlib/matplotlib/pull/31315/files#top
Show all changes 15 commits https://github.com/matplotlib/matplotlib/pull/31315/files
6ddad0a Implement warning for mismatched legend handles and labels EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/6ddad0a7d3cefad94a20bfc11dc95496ab651396
f6c86c4 Add regression test for legend argument mismatch EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/f6c86c406c9b63f7f43a7e14cfad0de2c8a7d3ce
11fd39a Fix regression test message for legend mismatch EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/11fd39a7d6d063d106c1352671abc4b1be7f3f62
36c98c1 Fix indentation for test_legend_mismatched_positional_args EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/36c98c193e2e27209907737f92318d53663da105
741c82b Update lib/matplotlib/legend.py EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/741c82bba1ee91ecbcd1f2840634b6fdf55e6c90
8a4de9e Rename test for legend mismatched arguments EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/8a4de9e66d30fd70eedaec93193684603ee54b59
b4fd2c1 Update lib/matplotlib/tests/test_legend.py EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/b4fd2c1bbba0344aa4c04b255311c584892210a0
d1cf688 Implement warning test for legend handle-label mismatch EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/d1cf688dd4e56234777246317e893b8ffb42b1da
a6eaea5 Add test for legend position argument handling EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/a6eaea528c5af191c6ef69109940bc5a98a25081
94a97ad Update warning message for legend handle mismatch EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/94a97adcd2544b56ba7614e5c35f3a6f6d30270c
7ecee3c Fix legend creation with list of labels EncryptedDoom Mar 16, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/7ecee3cb61fbeb0ec3797d1eac129211869fbf9f
b00fb58 Merge branch 'matplotlib:main' into main EncryptedDoom Mar 17, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/b00fb58c648b197ef08afca66f82b645edbf1fc7
b66aed1 gracefully handle generators in mismatch warning EncryptedDoom Mar 17, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/b66aed1c8fe4e98eaa6210ff6cc06a2d04dcee28
a70436f Update warning message for legend handle mismatch EncryptedDoom Mar 17, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/a70436f4eb74d2b3369136eb8ae304810c9b9a07
8aa5415 Update lib/matplotlib/legend.py EncryptedDoom Mar 17, 2026 https://github.com/matplotlib/matplotlib/pull/31315/commits/8aa5415a9f8ea50da91c06bede0e83930295930b
Clear filters https://github.com/matplotlib/matplotlib/pull/31315/files
Please reload this pagehttps://github.com/matplotlib/matplotlib/pull/31315/files
Please reload this pagehttps://github.com/matplotlib/matplotlib/pull/31315/files
legend.py https://github.com/matplotlib/matplotlib/pull/31315/files#diff-e7a00bb4a353fa623c1d0c1de5c6ca602b7ab38e8906d4842640983133b9196a
test_legend.py https://github.com/matplotlib/matplotlib/pull/31315/files#diff-1b573023d84935306a147bec7f137e59ae79c3d4f3bbea81152eb0c94b58a579
lib/matplotlib/legend.pyhttps://github.com/matplotlib/matplotlib/pull/31315/files#diff-e7a00bb4a353fa623c1d0c1de5c6ca602b7ab38e8906d4842640983133b9196a
View file https://github.com/matplotlib/matplotlib/blob/8aa5415a9f8ea50da91c06bede0e83930295930b/lib/matplotlib/legend.py
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/matplotlib/matplotlib/pull/31315/{{ revealButtonHref }}
https://github.com/matplotlib/matplotlib/pull/31315/files#diff-e7a00bb4a353fa623c1d0c1de5c6ca602b7ab38e8906d4842640983133b9196a
https://github.com/matplotlib/matplotlib/pull/31315/files#diff-e7a00bb4a353fa623c1d0c1de5c6ca602b7ab38e8906d4842640983133b9196a
lib/matplotlib/tests/test_legend.pyhttps://github.com/matplotlib/matplotlib/pull/31315/files#diff-1b573023d84935306a147bec7f137e59ae79c3d4f3bbea81152eb0c94b58a579
View file https://github.com/matplotlib/matplotlib/blob/8aa5415a9f8ea50da91c06bede0e83930295930b/lib/matplotlib/tests/test_legend.py
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/matplotlib/matplotlib/pull/31315/{{ revealButtonHref }}
https://github.com/matplotlib/matplotlib/pull/31315/files#diff-1b573023d84935306a147bec7f137e59ae79c3d4f3bbea81152eb0c94b58a579
https://github.com/matplotlib/matplotlib/pull/31315/files#diff-1b573023d84935306a147bec7f137e59ae79c3d4f3bbea81152eb0c94b58a579
https://github.com/matplotlib/matplotlib/pull/31315/files#diff-1b573023d84935306a147bec7f137e59ae79c3d4f3bbea81152eb0c94b58a579
https://github.com/matplotlib/matplotlib/pull/31315/files#diff-1b573023d84935306a147bec7f137e59ae79c3d4f3bbea81152eb0c94b58a579
Please reload this pagehttps://github.com/matplotlib/matplotlib/pull/31315/files
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.