-
Notifications
You must be signed in to change notification settings - Fork 168
Open
Labels
bugSomething isn't workingSomething isn't workingtriageIssues / Features awaiting triageIssues / Features awaiting triage
Milestone
Description
π Bug Summary
The make doctest
command fails with a database migration error because module-level code in main.py
executes database operations during pytest module import, even when only scanning for doctests.
π§© Affected Component
Select the area of the project impacted:
-
mcpgateway
- API -
mcpgateway
- UI (admin panel) -
mcpgateway.wrapper
- stdio wrapper - Federation or Transports
- CLI, Makefiles, or shell scripts
- Container setup (Docker/Podman/Compose)
- Other (explain below)
π Steps to Reproduce
- Clone the repository
- Set up the environment with make venv and make install-dev
- Run make doctest
π€ Expected Behavior
Doctests should run without triggering application startup or database operations
Module imports during doctest scanning should not have side effects
π Logs / Error Output
============================================================= ERRORS =============================================================
____________________________________________ ERROR collecting mcpgateway/main.py _____________________________________________
mcpgateway/main.py:155: in <module>
loop = asyncio.get_running_loop()
^^^^^^^^^^^^^^^^^^^^^^^^^^
E RuntimeError: no running event loop
During handling of the above exception, another exception occurred:
...
E sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) duplicate column name: slug
E [SQL: ALTER TABLE gateways ADD COLUMN slug VARCHAR]
Root Cause
Module-level code in mcpgateway/main.py (lines ~150-160) runs database initialization during import:
# This executes when the module is imported, not just when app starts
try:
loop = asyncio.get_running_loop()
except RuntimeError:
asyncio.run(bootstrap_db()) # β Runs migrations during import!
Proposed Solutions
Option 1 - Only run when script is executed directly, not imported
wait_for_db_ready(...)
try:
loop = asyncio.get_running_loop()
except RuntimeError:
asyncio.run(bootstrap_db())
Option 2: Move to FastAPI lifespan
@asynccontextmanager
async def lifespan(_app: FastAPI) -> AsyncIterator[None]:
logger.info("Starting MCP Gateway services")
try:
# Move database initialization here
wait_for_db_ready(...)
await bootstrap_db()
await tool_service.initialize()
# ... rest of existing initialization
Option 3: Doctest exclusion (Temporary workaround)
doctest:
python3 -m pytest --doctest-modules mcpgateway/ --ignore=mcpgateway/main.py --tb=short
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingtriageIssues / Features awaiting triageIssues / Features awaiting triage