-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
This page covers common issues encountered when running, developing, or deploying the IBF-SLM application. Each entry follows a Symptom → Cause → Fix structure.
- Startup Errors
- Database Connection Issues
- Authentication Errors
- Alembic Migration Errors
- Common Python / Dependency Errors
- Reading Logs
Symptom
ERROR: [Errno 98] Address already in use
Cause
Another process is already bound to the configured port (default 8000).
Fix Find and kill the conflicting process:
# identify the PID
lsof -ti tcp:8000
# kill it
kill -9 $(lsof -ti tcp:8000)Or start uvicorn on a different port:
uvicorn app.main:app --port 8001Symptom
ImportError: cannot import name 'X' from 'Y'
ModuleNotFoundError: No module named 'Z'
Cause Dependencies are missing or the virtual environment is not activated.
Fix
# activate the virtual environment first
source .venv/bin/activate # Linux/macOS
# or
.venv\Scripts\activate # Windows
# reinstall all dependencies
pip install -r requirements.txtIf the error persists, check that the correct Python version is active (python --version; must be 3.11+).
Symptom The process starts and stops with exit code 1 but little output.
Cause Usually a syntax error or import-time exception in the application code, or missing environment variables.
Fix Run with explicit reload and debug flags to surface the traceback:
uvicorn app.main:app --reload --log-level debugAlso verify that all required environment variables are set (database URL, secret key, etc.):
python -c "from app.core.config import settings; print(settings)"Symptom
asyncpg.exceptions.ConnectionRefusedError: Connection refused
sqlalchemy.exc.OperationalError: (asyncpg...) could not connect to server
Cause
PostgreSQL is not running, or the host/port in DATABASE_URL is wrong.
Fix
- Verify PostgreSQL is running:
pg_isready -h localhost -p 5432 # or systemctl status postgresql - Start it if needed:
systemctl start postgresql # systemd brew services start postgresql # macOS Homebrew
- Double-check
DATABASE_URLin your.envfile:DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/ibf_slm
Symptom
asyncpg.exceptions.InvalidPasswordError: password authentication failed for user "..."
Cause
The credentials in DATABASE_URL do not match the PostgreSQL role.
Fix
# reset the password in psql
psql -U postgres -c "ALTER USER ibf_slm_user WITH PASSWORD 'newpassword';"Update DATABASE_URL accordingly. If using pg_hba.conf peer authentication in development, ensure the OS user matches the PostgreSQL role name.
Symptom
asyncpg.exceptions.TooManyConnectionsError
sqlalchemy.exc.TimeoutError: QueuePool limit of size X overflow Y reached
Cause The SQLAlchemy async connection pool has been exhausted, often caused by unclosed sessions or a pool size that is too small for the load.
Fix
- Ensure every database session is properly closed. Use
async withortry/finally:async with AsyncSession(engine) as session: ...
- Tune pool settings in the engine configuration:
engine = create_async_engine( DATABASE_URL, pool_size=10, max_overflow=20, pool_timeout=30, )
- In development, confirm there are no leaked sessions by adding
echo_pool=Truetocreate_async_engine.
Symptom
asyncpg.exceptions.InvalidCatalogNameError: database "ibf_slm" does not exist
Cause
The database has not been created yet, or the name in DATABASE_URL is incorrect.
Fix
createdb -U postgres ibf_slm
# or via psql
psql -U postgres -c "CREATE DATABASE ibf_slm;"Then run migrations:
alembic upgrade headSymptom
Every request to a protected endpoint returns 401 Unauthorized, even with a valid-looking token.
Cause
-
SECRET_KEYenvironment variable is not set or does not match the key used to sign the token. - Token has expired.
- The
Authorizationheader format is wrong.
Fix
- Confirm
SECRET_KEYis set and consistent across restarts:echo $SECRET_KEY
- Verify the header format is exactly:
Authorization: Bearer <token> - Decode the token locally to inspect its claims and expiry:
If
import jose.jwt as jwt payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) print(payload)
expis in the past, the client must re-authenticate.
Symptom
Token decoding raises JWTError server-side.
Cause
The token was signed with a different SECRET_KEY (e.g., a previous key or a key from a different environment).
Fix
Rotate the secret key in .env and require all clients to obtain a new token. In production, use a secrets manager and avoid hardcoding keys.
Symptom
Login always returns 401 even with the correct password. The application logs may show a ValueError or AttributeError from passlib.
Cause
passlib does not support bcrypt 4.x / 5.x. The passlib library uses an internal bcrypt.__about__.__version__ attribute that was removed in newer versions of bcrypt.
Fix
Remove passlib and call bcrypt directly:
import bcrypt
def hash_password(plain: str) -> str:
return bcrypt.hashpw(plain.encode(), bcrypt.gensalt()).decode()
def verify_password(plain: str, hashed: str) -> bool:
return bcrypt.checkpw(plain.encode(), hashed.encode())Update requirements.txt:
# remove passlib
bcrypt>=4.0.0
Symptom
Stacktrace pointing into passlib/handlers/bcrypt.py.
Cause
Same as above: passlib introspects bcrypt.__about__ which no longer exists in bcrypt 4+.
Fix
See fix in the section above — replace passlib with direct bcrypt calls.
Symptom
alembic.util.exc.CommandError: Target database is not up to date.
Cause There are unapplied migrations in the database that must be resolved before generating a new one, or the database was modified outside of Alembic.
Fix
# check current revision
alembic current
# apply pending migrations
alembic upgrade head
# then generate new migration if needed
alembic revision --autogenerate -m "describe change"Symptom
alembic.util.exc.CommandError: Multiple head revisions are present for given argument 'head'
Cause Two developers created migrations from the same base revision, resulting in a branched history.
Fix Create a merge migration:
alembic merge heads -m "merge branch"
alembic upgrade headReview the generated merge migration to ensure no conflicting schema changes are present.
Symptom
alembic.util.exc.CommandError: Can't locate revision identified by 'abc123'
Cause
The alembic_version table in the database references a revision file that no longer exists in alembic/versions/.
Fix
- Check the current version recorded in the DB:
psql $DATABASE_URL -c "SELECT * FROM alembic_version;"
- If the file was deleted by mistake, restore it from version control.
- If intentionally removed, manually update the version table to a valid revision:
Then run
psql $DATABASE_URL -c "UPDATE alembic_version SET version_num = '<valid_revision>';"
alembic upgrade head.
Symptom
alembic revision --autogenerate creates a migration with no op.* calls.
Cause
- SQLAlchemy models were not imported before
target_metadatais read inenv.py. - The models are defined but not referenced by the metadata object.
Fix
In alembic/env.py, ensure all models are imported before target_metadata is assigned:
from app.models import * # noqa: F401, F403
from app.db.base import Base
target_metadata = Base.metadataSymptom
AttributeError: ...
TypeError: ...
Stacktrace originates inside sqlalchemy/ with no obvious application code cause.
Cause
SQLAlchemy versions below 2.0.36 are incompatible with CPython 3.14 due to internal interpreter changes.
Fix
pip install "sqlalchemy>=2.0.36"Pin in requirements.txt:
SQLAlchemy>=2.0.36
Symptom
ImportError: greenlet is required for async support
Cause
The greenlet package is missing. It is required by SQLAlchemy's async engine even though it is an optional dependency.
Fix
pip install "sqlalchemy[asyncio]"
# which installs greenlet as a dependencySymptom
ModuleNotFoundError: No module named 'asyncpg'
Cause
asyncpg is not installed.
Fix
pip install asyncpgAdd to requirements.txt:
asyncpg>=0.29.0
Symptom
ModuleNotFoundError: No module named 'jose'
or unexpected behavior from the wrong jose package.
Cause
The package is installed as python-jose on PyPI but imported as jose. A plain jose package also exists on PyPI and shadows it.
Fix
pip uninstall jose python-jose
pip install python-jose[cryptography]Import as:
from jose import jwt, JWTErrorSymptom
pip reports resolver conflicts, or the app crashes with unexpected AttributeError/ImportError at runtime after updating a package.
Fix Use a pinned requirements file and a virtual environment:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtTo regenerate a fully-pinned lockfile:
pip freeze > requirements.lockIn CI, install from the lockfile to guarantee reproducibility.
By default uvicorn writes to stdout. Increase verbosity with:
uvicorn app.main:app --log-level debugLog levels in order of decreasing verbosity: debug, info, warning, error, critical.
To write logs to a file:
uvicorn app.main:app --log-level info 2>&1 | tee app.logThe application uses Python's standard logging module. Useful patterns:
# filter for errors only
grep -i "error\|exception\|traceback" app.log
# show lines around a specific exception
grep -A 20 "Traceback" app.log
# tail live
tail -f app.logTo see every SQL statement issued (useful for debugging N+1 queries or incorrect joins), enable engine echo:
engine = create_async_engine(DATABASE_URL, echo=True)Or set the log level for the SQLAlchemy logger:
import logging
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)Note: Do not leave
echo=TrueorINFO-level engine logging enabled in production — it is extremely verbose and may expose sensitive data in logs.
alembic -v upgrade head # verbose migration output
alembic history --verbose # full revision history with details
alembic current --verbose # show current applied revision# connect to the database
psql $DATABASE_URL
# check applied migrations
SELECT * FROM alembic_version;
# list tables
\dt
# describe a table
\d+ usersFor issues not covered here, check the SQLAlchemy async docs, the Alembic docs, and the FastAPI docs. Open an issue in the project repository with the relevant log output and your environment details.