Skip to content

Add B047: except handler shadowed by an earlier one - #589

Merged
cooperlees merged 3 commits into
PyCQA:mainfrom
LuisFigueroaG:feat/unreachable-except-handlers
Oct 9, 2026
Merged

cooperlees merged 3 commits into
PyCQA:mainfrom
LuisFigueroaG:feat/unreachable-except-handlers

Conversation

@LuisFigueroaG

Copy link
Copy Markdown
Contributor

B047 reports an except handler that can never run because an earlier handler in the same try already catches a parent class:

try:
    ...
except Exception:
    ...
except ValueError:  # B047
    ...

It also covers except BaseException: followed by except Exception: or a bare except:, which was the first case in the issue. Works for except* too, and for names inside tuples.

Like B014, it only looks at builtin exceptions since we can't know the hierarchy of other classes from the AST. Catching the exact same name twice is still left to B025.

B047 is the next free code after B045 and B046. Happy to renumber if needed.

Closes #349

Tested with pytest tests/test_bugbear.py (3.10, 3.12, 3.13, 3.14), pre-commit run --all-files, and running it over the stdlib and site-packages with --select B047, which found nothing.

A handler like `except ValueError:` placed after `except Exception:` can
never run, since the earlier handler already catches every ValueError.
The same goes for a bare `except:` after `except BaseException:`.

Like B014, only builtin exceptions are checked, since we can't know the
hierarchy of other classes from the AST. Catching the exact same name
twice is still left to B025.

Closes PyCQA#349
…cept-handlers

# Conflicts:
#	README.rst
#	bugbear.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

B047 misses unreachable builtin exceptions inside valid starred handler tuples.

1 open finding
What changed in this PR

This PR adds B047 to flake8-bugbear to flag except and except* handlers shadowed by earlier handlers for builtin exceptions.

Changes:

  • Add the B047 check and diagnostic message.
  • Add examples and regression tests for ordinary and starred exception handlers.
  • Document B047 in the README and unreleased changelog.
File Description
tests/​eval_files/​b047.py Tests ordinary handler ordering.
tests/​eval_files/​b047_py311.py Tests except* ordering.
README.rst Documents B047 and its release note.
bugbear.py Implements and registers B047.

🧠 Review effort: Lite


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread bugbear.py Outdated
Comment on lines +2224 to +2225
elif isinstance(handler.type, ast.Tuple):
names = [e.id for e in handler.type.elts if isinstance(e, ast.Name)]

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, B047 now collects names through _flatten_excepthandler, so starred tuple entries are expanded, and the except (*(ValueError,),): case is covered in b047.py.

@cooperlees
cooperlees merged commit 6240705 into PyCQA:main Oct 9, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Report on uncatchable exception handlers (?)

3 participants