Troubleshooting Guide
Runtime Errors
ConfigurationError at startup
Cause: Invalid RestEndpoint or LightApi configuration detected before any request is served.
Common causes:
- Field annotation type not in the type map (use
str,int,float,bool,datetime,Decimal,UUID) Meta.paginationuses an invalidstylevalue orpage_size < 1Meta.cachehasttl < 1- Async engine used without
lightapi[async]installed - YAML
${VAR}references an unset environment variable
# ❌ Wrong — list is not in the type map
class BadEndpoint(RestEndpoint):
tags: list
# ✅ Fix — use a supported type; store as JSON string if needed
class GoodEndpoint(RestEndpoint):
tags: str = Field(default="")
401 Unauthorized on all requests
Cause: JWT authentication is enabled but the request is missing a valid token.
- Ensure
LIGHTAPI_JWT_SECRETis set and matches the secret used to sign tokens. - Send
Authorization: Bearer <token>with every request. - Generate a token:
import os
os.environ["LIGHTAPI_JWT_SECRET"] = "your-secret"
from lightapi.authentication import JWTAuthentication
auth = JWTAuthentication()
token = auth.generate_token({"sub": "1", "is_admin": False})
print(token)
422 Unprocessable Entity
Pydantic validation failed. Check the response body for the specific failing field:
{
"detail": [
{"type": "string_too_short", "loc": ["name"], "msg": "String should have at least 1 character", ...}
]
}
405 Method Not Allowed
The endpoint was registered with HttpMethod mixins that exclude the attempted verb:
# Only GET is allowed — POST returns 405
class ReadOnlyEndpoint(RestEndpoint, HttpMethod.GET):
title: str
Remove the mixin restriction or add the required method mixin.
Configuration Issues
JWT secret not configured
Port already in use
CORS preflight blocked
Pass allowed origins to LightApi:
Use ["*"] for development only.
Database Issues
Table does not exist (Meta.reflect)
Specify the correct table name:
SQLAlchemy URL format
# SQLite
"sqlite:///app.db"
"sqlite:///./app.db"
# PostgreSQL (sync)
"postgresql+psycopg2://user:pass@localhost:5432/mydb"
# PostgreSQL (async)
"postgresql+asyncpg://user:pass@localhost:5432/mydb"
# MySQL
"mysql+pymysql://user:pass@localhost:3306/mydb"
Async engine without async extras
Middleware Issues
Middleware registration
Register middleware via LightApi, not app.add_middleware() (which does not exist in v2):
# ✅ v2 — pass to constructor
from lightapi import LightApi
from lightapi.core import Middleware
class MyMiddleware(Middleware):
def process(self, request, response):
return response
app = LightApi(engine=engine, middlewares=[MyMiddleware])
Middleware process() signature
The process method takes two arguments: request and response. response is None during pre-processing:
class MyMiddleware(Middleware):
def process(self, request, response):
if response is None:
# pre-processing
return None
# post-processing
return response
Caching Issues
Redis unreachable
LightAPI emits a RuntimeWarning if Redis cannot be reached at startup and silently disables caching. Set LIGHTAPI_REDIS_URL to the correct URL:
Verify:
Performance Tips
Indexes
Declare indexes on frequently queried columns:
class UserEndpoint(RestEndpoint):
email: str = Field(unique=True, index=True)
username: str = Field(index=True)
Use async for high-concurrency workloads
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/mydb")
app = LightApi(engine=engine)
Filtering instead of post-processing
Use Meta.filtering rather than filtering results in Python — let the database do the work.
Environment Variables Reference
| Variable | Description | Default |
|---|---|---|
LIGHTAPI_DATABASE_URL |
Database URL when no engine is given | — (required) |
LIGHTAPI_JWT_SECRET |
JWT signing secret | — (required) |
LIGHTAPI_REDIS_URL |
Redis connection URL | redis://localhost:6379/0 |
Minimal working example
import os
from sqlalchemy import create_engine
from lightapi import LightApi, RestEndpoint, Field, Authentication
from lightapi.authentication import JWTAuthentication, IsAuthenticated
os.environ["LIGHTAPI_JWT_SECRET"] = "dev-secret-at-least-32-bytes-long"
class ItemEndpoint(RestEndpoint):
name: str = Field(min_length=1)
price: float = Field(ge=0)
class Meta:
authentication = Authentication(
backend=JWTAuthentication,
permission=IsAuthenticated,
)
engine = create_engine("sqlite:///app.db")
app = LightApi(engine=engine, cors_origins=["*"])
app.register({"/items": ItemEndpoint})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)