Fix Sentry Not Receiving Errors From Django in Production
Fix Sentry showing no events from a production Django app: check the DSN and environment, initialize sentry-sdk early in settings, make sure Celery and Gunicorn workers initialize too, and look for sampling, filters, rate limits, and blocked outbound traffic.
Problem statement
Users report 500 errors, the logs show tracebacks, but the Sentry project is empty, or it receives errors from the web app and nothing from Celery. Sentry fails quietly by design: if the SDK is not initialized, has no DSN, cannot reach Sentry, or decides to drop an event, your app keeps running and nothing tells you. You have to check each link in the chain.
- Send a test from the server:
python manage.py shell -c "import sentry_sdk; sentry_sdk.capture_message('test'); sentry_sdk.flush()". - Check the DSN is set in production: an empty DSN disables the SDK without error.
- Call
sentry_sdk.init()in settings, so every process that loads Django initializes it, including Celery workers. - Look for
sample_rate,before_send, orignore_errorssettings dropping events. - Check the project's Stats page for dropped events (rate limits, spike protection, quota).
Step-by-step solution
1. Send a test event
python manage.py shell -c "
import sentry_sdk
print('client active:', sentry_sdk.get_client().is_active())
sentry_sdk.capture_message('sentry test from production')
sentry_sdk.flush(timeout=5)
"
If is_active() is False, the SDK never initialized with a DSN in this process. If it is True and nothing arrives, the event was dropped or blocked on the way.
2. Initialize in settings with the DSN
# settings/production.py
import sentry_sdk
SENTRY_DSN = os.environ.get("SENTRY_DSN", "")
if SENTRY_DSN:
sentry_sdk.init(
dsn=SENTRY_DSN,
environment=os.environ.get("SENTRY_ENVIRONMENT", "production"),
release=os.environ.get("GIT_SHA"),
send_default_pii=False,
traces_sample_rate=0.1,
)
The Django integration is enabled automatically when Django is installed. Putting init() in settings means Gunicorn workers, management commands, and Celery all initialize it, because they all load settings. Initializing in wsgi.py only covers the web process.
3. Check filters and sampling
sentry_sdk.init(
dsn=SENTRY_DSN,
sample_rate=1.0, # errors: keep at 1.0
traces_sample_rate=0.1, # performance only
before_send=drop_noise,
)
sample_rate below 1.0 drops a share of error events. traces_sample_rate affects only performance data, not errors. A before_send hook that returns None too broadly, or an ignore_errors list with a base class like Exception, hides everything. Errors that Django handles itself, such as Http404 and PermissionDenied, are not reported by design.
4. Make sure errors are not swallowed
If your code catches exceptions and returns a response, Sentry never sees them. Report them explicitly:
try:
sync_order(order)
except ExternalAPIError:
sentry_sdk.capture_exception()
return JsonResponse({"error": "sync failed"}, status=502)
Logged errors are captured too: the logging integration sends logger.error() records as events by default.
5. Check delivery
From the server, confirm outbound HTTPS to Sentry works:
curl -sS -o /dev/null -w "%{http_code}\n" https://o123456.ingest.sentry.io/api/123/envelope/
Any HTTP status (often 400 or 405 without a body) proves connectivity; a timeout means a firewall or egress rule blocks it. Then check the Sentry project's Stats page: events dropped by rate limits, spike protection, or an exhausted quota appear there, not in your app.
Explanation
The Sentry SDK hooks into Django's request handling and Python's logging, builds an event for each unhandled exception, applies sampling and your filters, and sends it from a background thread. Every step is designed to never break the app: a missing DSN disables the SDK, network errors are swallowed, and dropped events are counted on the server side. That makes Sentry safe to run and easy to misconfigure without noticing.
Edge cases / notes
- Short-lived processes. Cron commands that exit immediately can quit before the background thread sends; call
sentry_sdk.flush()at the end. - Forking. Initializing before Gunicorn forks (with
preload_app) is supported, but initializing in a post-fork hook is safer for some transports. - Self-hosted. For self-hosted Sentry or GlitchTip, the DSN host must be reachable from production networks, not just your office.
Next steps
- Configure Sentry fully with Set Up Sentry for Django in Production.
- Control event volume and cost with Sentry Performance Sampling for Django.
- Cover the rest of observability with the Django Monitoring Checklist.
FAQ
Why does Sentry not report 404 errors?
Django handles Http404 itself and returns a response, so the SDK does not treat it as an error. That is intended.
Does traces_sample_rate affect errors?
No. It controls performance traces. Error sampling is sample_rate, which should usually stay at 1.0.
Why do Celery task errors not show up?
Sentry was probably initialized only in wsgi.py. Initialize it in settings so workers load it too.
How do I know if events are being dropped by quota?
Open the project's Stats page in Sentry. It shows accepted, filtered, and dropped events with reasons.