You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
No blanket except: — name the exception, or except Exception: with a comment when the swallow is deliberate.
The rule is right. 30 handlers in the codebase do not follow it, swallowing everything with no comment saying why.
These numbers were recounted against main on 1 August 2026, after #54 annotated its five. An earlier version of this issue said 25, which was wrong in both directions — moon_extract.py alone has 23, and three of the files #54 touched still have unannotated handlers elsewhere.
Most are almost certainly deliberate — this is a codebase that talks to a browser over CDP and to hosts that change behaviour without notice, so defensive swallowing is often the correct call. That is exactly why the rule asks for a comment: from the outside, a deliberate swallow and a forgotten one look identical, and the next person cannot tell which is which.
The moon_extract.py ones matter most. Several of them currently mean a broken selector is indistinguishable from a dead link, which is the class of bug that costs someone an afternoon of debugging the wrong thing.
Take a slice — four people can work in parallel
Claim one slice by commenting which you are taking. Do not take two.
Slice D touches four files but is the smallest and most self-contained — a good one if it is your first PR here.
What to do
For each handler in your slice:
If a narrower exception is obviously right — name it. except (OSError, asyncio.TimeoutError): says far more than except Exception:. refactor(cleanup): annotate exception swallows in moon_bridge.py and … #54 narrowed native_dialog to (subprocess.TimeoutExpired, OSError) and that is the standard to follow.
If the swallow is deliberate and has to stay broad — add a one-line comment saying what is expected to fail and why continuing is correct. State a specific fact. "Best-effort cleanup during shutdown" is a reason; "just in case" is not.
If you cannot work out why it is there — leave it and say so in the PR. A # unclear note from a contributor is more useful than a confident guess, and I can fill it in.
Do not change behaviour beyond narrowing an exception set you are confident about. No new logging, no refactoring, no reordering.
Acceptance criteria
Every handler in the claimed slice is either narrowed or carries a one-line reason
No comment restates the code (# catch exception is not a reason)
pytest tests/ -q passes
Nothing outside the claimed slice is modified
The PR says which slice it covers
Notes for the contributor
No Windows needed.pytest tests/ -q stubs Chrome and the network at the moon_extract boundary, so the suite runs on Linux and macOS.
The useful skill here is reading a defensive handler and working out what it is actually defending against. That is worth more than the diff, and it is why a PR that says "these four are deliberate, this fifth one I could not explain" is a better PR than one that comments all five confidently.
Context
CONTRIBUTING.mdstates the rule:The rule is right. 30 handlers in the codebase do not follow it, swallowing everything with no comment saying why.
These numbers were recounted against
mainon 1 August 2026, after #54 annotated its five. An earlier version of this issue said 25, which was wrong in both directions —moon_extract.pyalone has 23, and three of the files #54 touched still have unannotated handlers elsewhere.moon_extract.pymoon_engine.pymoon_bridge.pymoon_cli.pymoon_download.pyMost are almost certainly deliberate — this is a codebase that talks to a browser over CDP and to hosts that change behaviour without notice, so defensive swallowing is often the correct call. That is exactly why the rule asks for a comment: from the outside, a deliberate swallow and a forgotten one look identical, and the next person cannot tell which is which.
The
moon_extract.pyones matter most. Several of them currently mean a broken selector is indistinguishable from a dead link, which is the class of bug that costs someone an afternoon of debugging the wrong thing.Take a slice — four people can work in parallel
Claim one slice by commenting which you are taking. Do not take two.
moon_extract.pylines 101–556moon_extract.pylines 653–943moon_extract.pylines 1025–1249moon_engine.py,moon_bridge.py,moon_cli.py,moon_download.pySlice D touches four files but is the smallest and most self-contained — a good one if it is your first PR here.
What to do
For each handler in your slice:
except (OSError, asyncio.TimeoutError):says far more thanexcept Exception:. refactor(cleanup): annotate exception swallows in moon_bridge.py and … #54 narrowednative_dialogto(subprocess.TimeoutExpired, OSError)and that is the standard to follow.# unclearnote from a contributor is more useful than a confident guess, and I can fill it in.Do not change behaviour beyond narrowing an exception set you are confident about. No new logging, no refactoring, no reordering.
Acceptance criteria
# catch exceptionis not a reason)pytest tests/ -qpassesNotes for the contributor
No Windows needed.
pytest tests/ -qstubs Chrome and the network at themoon_extractboundary, so the suite runs on Linux and macOS.The useful skill here is reading a defensive handler and working out what it is actually defending against. That is worth more than the diff, and it is why a PR that says "these four are deliberate, this fifth one I could not explain" is a better PR than one that comments all five confidently.
Comment with your slice letter before you start.