fix: avoid NameError in check_external_config_db when the DB is unreachable#10052
fix: avoid NameError in check_external_config_db when the DB is unreachable#10052dpage wants to merge 1 commit into
Conversation
WalkthroughThis PR fixes a crash that occurs when checking an unreachable external configuration database during pgAdmin startup. The fix replaces manual connection handling with a context manager to prevent a secondary ChangesConnection Lifecycle Safety Refactoring
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…chable check_external_config_db() closed the connection in a finally block, but when engine.connect() itself failed (e.g. an unreachable external config database) the `connection` local was never bound, so the finally raised UnboundLocalError and masked the intended `return False`. Use the connection as a context manager so it is closed on every path without referencing an unbound name, and dispose the engine in finally. The function now returns False cleanly on connection failure.
412dda1 to
52016df
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
web/pgadmin/utils/check_external_config_db.py (1)
20-25: ⚡ Quick winConsider binding and using the connection explicitly.
The context manager opens a connection but doesn't bind it to a variable, then
inspect(engine)is called which may obtain a different connection from the pool. While the current code works correctly, it would be clearer to bind the connection and pass it directly toinspect().♻️ Proposed refactor for clarity
- # The context manager closes the connection on every path. The - # previous "finally: connection.close()" raised NameError when - # engine.connect() itself failed (e.g. an unreachable database), - # masking the intended "return False". - with engine.connect(): - return inspect(engine).has_table("server") + # The context manager closes the connection on every path. The + # previous "finally: connection.close()" raised NameError when + # engine.connect() itself failed (e.g. an unreachable database), + # masking the intended "return False". + with engine.connect() as conn: + return inspect(conn).has_table("server")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/pgadmin/utils/check_external_config_db.py` around lines 20 - 25, Bind the connection returned by engine.connect() and pass that connection into inspect() instead of inspecting the engine directly; specifically, replace the unbound context manager use with a bound one (e.g. with engine.connect() as conn:) and call inspect(conn).has_table("server") so the same connection is used and closed by the context manager (refer to engine.connect() and inspect()).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@web/pgadmin/utils/check_external_config_db.py`:
- Around line 20-25: Bind the connection returned by engine.connect() and pass
that connection into inspect() instead of inspecting the engine directly;
specifically, replace the unbound context manager use with a bound one (e.g.
with engine.connect() as conn:) and call inspect(conn).has_table("server") so
the same connection is used and closed by the context manager (refer to
engine.connect() and inspect()).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 7faddb6b-25a0-4c62-94b6-e0194900ba51
📒 Files selected for processing (2)
docs/en_US/release_notes_9_16.rstweb/pgadmin/utils/check_external_config_db.py
Problem
check_external_config_db()(used by the Docker entrypoint to decide whether to run first-launch user setup) closes its connection in afinallyblock:When
engine.connect()itself fails — e.g. the external config database is unreachable — theconnectionlocal is never bound, so thefinallyraisesUnboundLocalError, which propagates out and masks the intendedreturn False.Surfaced while reviewing #10009 (the entrypoint now tolerates a non-zero exit from this script, but the function should still behave correctly on its own).
Fix
Use the connection as a context manager (closed on every path, no unbound-name reference) and dispose the engine in
finally:Verification (live PostgreSQL 18)
servertableFalseFalseservertable presentTrueTrueUnboundLocalErrorFalsepycodestyleclean.Summary by CodeRabbit