# Fix Sentry Errors in a Django App

Send the Sentry issue to an agent: it reads the Django stack trace, reproduces the error with a failing TestCase, fixes the view or model and opens a pull request.

[Run this on Rush](https://cloud.getrush.ai/run/fix-sentry-errors/django/), in a Project that has your repository.

## What the agent does

The agent reads the issue after the prompt and pulls its latest event through the Sentry connection: the exception class and message, the transaction, the breadcrumbs with the SQL and HTTP calls before the failure, the release tag and the in-app frames. For a Django app the transaction is already a function name when the SDK is set up that way, which is the case in django/djangoproject.com: `djangoproject/settings/prod.py` calls `sentry_sdk.init` with `DjangoIntegration(transaction_style="function_name")` and `RedisIntegration()`, with a 0.1 traces sample rate, when a `sentry_dsn` is present in the secrets file and `DEBUG` is off.

That site is a Django 6.1.1 project on Python 3.12 with Postgres 17, `django-hosts` 7.0 and several apps: `accounts`, `aggregator`, `blog`, `checklists`, `contact`, `dashboard`, `docs`, `foundation`, `fundraising`, `legacy`, `members`, `releases`, `svntogit` and `tracdb`. `djangoproject/hosts.py` routes the `www`, `docs` and `dashboard` hostnames to three URL confs, so a transaction such as `docs.views.document` or `fundraising.views.configure_checkout_session` tells the agent both the app and the hostname. It opens the view the frame names, its form or model, and the template if the exception came from rendering.

The common shapes are specific to each app. `docs/views.py` serves `document`, `search_results` and `search_suggestions` for a language and version, so a `DoesNotExist` or a `KeyError` on a release that has no built docs lands there. `fundraising/views.py` talks to Stripe 13.2 in `configure_checkout_session`, `receive_webhook` and `WebhookHandler`, so an unexpected event shape or a missing `DjangoHero` raises there. `blog/views.py` is a set of date-based generic views, and `releases/views.py` has `roadmap` and `redirect` with version parsing. The agent reads the breadcrumbs for the URL and query parameters and builds the request that reproduces the frame.

Tests live beside each app, as `tests.py` or a `tests/` package: `docs/tests/test_views.py`, `fundraising/tests/test_views.py`, `blog/tests.py`, `releases/tests.py`. The agent adds one test method to the matching module, using the Django test client against the hostname `django-hosts` expects, confirms it fails with the Sentry exception, fixes the view or model, and runs `python -m manage test <app>` the way `Makefile`'s `test` target does, after creating the two Postgres databases and the `conf/secrets.json` the `tests.yml` workflow shows. It then opens a pull request that links the Sentry issue and quotes the frames and the test output. If it cannot reproduce the error, it stops at `needs_review` and says what it tried.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "A Sentry issue for this Django repository is attached below. Read its latest event through the Sentry connection: the exception, the transaction (a view function name), the breadcrumbs with the request URL, query string and SQL, the release tag and the in-app frames. Open the view the frame names and its form, model or template; the apps are routed by djangoproject/hosts.py, so use the www, docs or dashboard URL conf the transaction belongs to. Add one test method to that app's tests.py or tests/test_views.py that performs the same request with the test client and confirm it fails with the same exception. Fix the cause rather than catching the exception, run python -m manage test for that app with the two Postgres databases and the conf/secrets.json the tests workflow sets up, and open a pull request that links the Sentry issue, quotes the frames and the failing test output and explains the cause. Stop at needs_review if you cannot reproduce it.\n\nSentry issue:\n{issue}",
  "connections": [
    "sentry"
  ],
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request that changes one view, form or model in a single app and adds one test method beside it, for example a case in `docs/tests/test_views.py` that requests a document for a version with no built docs and now gets a 404 instead of a 500. The description links the Sentry issue, names the transaction and the frame, states the cause, and shows the test failing before and passing after, with the `manage test` summary for that app.

The reviewer checks that the test goes through the URL conf for the right hostname, that the fix handles the input the breadcrumbs showed rather than wrapping the view in a broad except, and that a 404 or a redirect is the right answer for a user rather than a silent empty page. For the fundraising app, a change in `WebhookHandler` should keep Stripe signature checking as it was.

A run that ends `needs_review` has no pull request; its result explains what the agent tried, for example that the query parameters in the breadcrumbs no longer reach the view after a recent URL change, so a person can decide whether the issue is already resolved.

## Run it on every Sentry issue alert

Create an alert rule in the Sentry project for new issues with a webhook action pointed at a handler on your server. The handler sends this request with the issue JSON after the prompt and the Sentry issue id as `Idempotency-Key`, so a retried delivery returns the run already started. Sentry cannot send the `Authorization: Bearer` header a Rush `webhook` trigger requires, so the handler is what forwards, either to `POST /o/{org}/sessions` or to an automation's trigger in the Project.

Give the API key a webhook URL to receive `run.completed` or `run.failed` with the `session_url`, and let the handler comment the pull request link on the Sentry issue. Noisy issues that fire many times an hour should be deduplicated by issue id in the handler, or capped with the automation's `max_runs_per_hour`.

## Why run it on Rush?

A multi-app Django site with two databases, a Trac import and host-based routing takes real time to stand up locally, and a Sentry error from the fundraising app is not something a volunteer wants to reproduce against Stripe by hand. The agent builds that environment in its own sandbox from the same steps the CI workflow uses, and the maintainer sees a pull request with a failing test instead of a stack trace.

Each pull request carries its evidence: the event that was read, the test that failed with the same exception, the `manage test` output after the fix. Several issues can be several sessions at once, each isolated, and a run that cannot reproduce its issue says so rather than guessing.

## Frequently asked questions

### How does the agent know which app and hostname an error belongs to?

From the transaction, which `DjangoIntegration(transaction_style="function_name")` sets to the view's dotted path, and from `djangoproject/hosts.py`, which maps `www`, `docs` and `dashboard` to their URL confs. The test then sets the matching `HTTP_HOST` so `django-hosts` resolves the right routes.

### Does the sandbox need the Trac database?

For `tracdb` and the dashboard, yes, and the `tests.yml` workflow shows how: a second Postgres database loaded from `tracdb/trac.sql`. For an error in `docs`, `blog` or `fundraising` the agent still creates both databases so the test settings load, but the test itself touches only the main one.

### Will it fix the error by adding a try/except around the view?

No. The prompt asks for the cause. A `DoesNotExist` for a missing release should become a `get_object_or_404`, a bad query parameter should be validated in the form, and a Stripe event with an unexpected shape should be handled in `WebhookHandler` for that event type.

### Which test runner and command does it use?

Django's own, through `python -m manage test <app>`, which is what the `Makefile` `test` target wraps with coverage. It installs `requirements/tests.txt`, which pins Django 6.1.1, psycopg 3.3.4, `requests-mock` and `time-machine`, and runs only the app the issue belongs to.

### What if the issue is from a release that no longer matches main?

The agent compares the event's release tag with the current code. If the frame is already gone, the pull request still adds the test for the current behavior, says the issue is likely resolved, and leaves resolving it in Sentry to a person.
