# Fix Actix Web Errors from Sentry Alerts

Yes. An agent reads the Sentry event, reproduces the Actix Web error with an init_service test, fixes the handler and opens a PR with test and clippy output.

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

## What the agent does

The agent reads the alert payload after the prompt, then opens the issue and its latest event through the Sentry connection. For an Actix Web service the parts that matter are the exception type and message, the in-app frames with their module paths, and the request context the `sentry-actix` middleware attaches: method, path, status and the headers it kept. From those it knows which handler or extractor failed and with what input, which is what the test has to reproduce.

Then it reads the workspace the way the official examples are laid out. In actix/examples the root `Cargo.toml` is a workspace with resolver 3, edition 2024 and `rust-version` 1.98, with 74 member crates from `auth/casbin` to `websockets/echo`, and every version is set once in `[workspace.dependencies]`: `actix-web` 4.11, `actix-session` 0.11, `actix-multipart` 0.8, `actix-ws` 0.4, `awc` 3.7, `serde_json` 1, `tracing-actix-web` 0.7.22 and `actix-test` 0.1 for crates that spin up a real server in tests. Only 14 source files in the whole workspace hold a test module, so for most members the agent writes the first test the crate has had.

The test follows the style the repository already uses. `basics/hello-world/src/main.rs` builds the app with `test::init_service(App::new().route("/", web::get().to(index)))`, sends `test::TestRequest::get().uri("/")` and checks the status and body with `to_bytes`; `json/json/src/main.rs` posts a struct with `set_json`; `guards/src/main.rs` sets an `Accept-Version` header and reads the body with `call_and_read_body`. The agent writes one `#[actix_web::test]` in a `#[cfg(test)]` module of the crate the frames name, builds the exact request from the event, and asserts the status the service should have returned. For a JSON extraction error it looks at how `json/json-decode-error` maps `JsonPayloadError::ContentType` to 415, data errors to 422 and the rest to 400 through `web::JsonConfig::error_handler`, and how `json/json-error` implements `ResponseError` to build the error body, because the fix is often a missing handler of that shape rather than a change inside the route.

With the test failing for the same reason the event shows, the agent changes the handler, the extractor configuration or the error type, and runs what the repository's own CI runs: `cargo check --workspace --bins --examples --tests`, then `cargo test --workspace --all-features --no-fail-fast --exclude=db-diesel -- --nocapture`, and `cargo clippy --workspace --all-features --tests -- -D warnings` from `clippy-fmt.yml`. The CI workflow also creates the SQLite database for `basics/todo` with `sqlx database create` and `sqlx migrate run`, and starts `redis-server` for the cache and session examples, so the agent does the same when the failing crate is one of those. A fix that only moves the panic, or a test that passes without the fix, is a reason to stop and report rather than open a pull request.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "A Sentry alert fired for this Actix Web service; its payload follows this prompt. Use the Sentry connection to read the issue, its latest event, the in-app frames with their module paths, and the request context (method, path, status, headers) the sentry-actix middleware attached. In a workspace shaped like actix/examples, find the member crate the frames name and read its handlers, extractors and error types. Add one #[actix_web::test] in a #[cfg(test)] module of that crate, using test::init_service and test::TestRequest with the exact request from the event, and confirm it fails the way the event shows. Fix the cause in the handler, the extractor configuration or the ResponseError implementation; do not catch the panic or swallow the error. Run cargo check --workspace --bins --examples --tests, cargo test --workspace --all-features --no-fail-fast --exclude=db-diesel, and cargo clippy --workspace --all-features --tests -- -D warnings; start Redis or create the SQLite database first if the crate needs one, as .github/workflows/ci.yml does. Open a pull request that links the Sentry issue, quotes the frames and the failing test output, and explains the cause. If it does not reproduce, stop and report what you tried.\n\nAlert payload:\n{payload}",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ],
  "connections": [
    "sentry"
  ]
}
```

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 member crate and adds or extends a `#[cfg(test)]` module in it. Its description links the Sentry issue, quotes the exception message and the in-app frames, shows the new test failing before the change and passing after, and gives the `cargo test --workspace` summary and the clippy result. `Cargo.lock` changes only when a dependency had to be added, and the workspace manifest does not change.

Before merging, a reviewer checks that the request in the test matches the one in the event rather than a convenient variant, that an error path now answers a 4xx with a body shaped like the crate's other errors instead of a 500, and that no `unwrap` was traded for a silent default. When the event came from a release older than main and the handler has since changed, the description says so and the test pins the current behavior.

## Run it on every Sentry issue alert

Create an alert rule in the Sentry project for the service with a webhook action pointed at a handler on your server. Sentry signs its own requests and cannot add the `Authorization: Bearer` header a Rush `webhook` trigger needs, so the handler receives the alert, places its JSON after the prompt in `input`, and sends this request with the Sentry issue id as `Idempotency-Key`, so a redelivered alert returns the run already started instead of a second one.

Give the API key a webhook URL and Rush POSTs `run.completed` with `session_url` and the result when the turn ends; the handler can comment the pull request link on the Sentry issue. A service with many routes can see several issues in a minute, and a key has at most `max_concurrent` runs in progress, so the handler queues alerts past that limit rather than dropping them on a 429.

## Why run it on Rush?

An Actix Web error report names a handler and a request; reproducing it on a laptop means checking out the right commit, building a workspace with 74 crates, starting Redis or SQLite for the ones that need them, and crafting the request by hand. On Rush the agent does that in its own sandbox with the toolchain `rust-version` asks for, runs the one crate's tests and then the whole workspace, and hands back a diff. Several alerts are several sandboxes at once.

The record is the evidence. The transcript shows the Sentry event the agent read, the test failing with the same message and passing after the change, and the exact `cargo test` and `clippy -D warnings` output, so the reviewer reads a fix with its proof instead of rebuilding the request from a stack trace.

## Frequently asked questions

### The service uses actix-test and a real server in its tests. Does that matter?

No. The agent follows whatever the crate already does: `auth/redis-session` lists `actix-test` in its dev-dependencies and starts a server, while most members use `test::init_service` in process. A new test goes beside the existing ones in the same style, so the diff reads like the rest of the file.

### What if the frames are inside actix-web or a middleware crate?

The agent walks up to the first in-app frame, the handler or extractor the service owns, and reproduces from there. If the event shows a bug in a dependency, the pull request pins the behavior with a test, works around it in the service's code, and says which crate and version are involved rather than patching the dependency.

### Will it change the workspace dependencies?

Not for a fix. Versions live in `[workspace.dependencies]` and a bump there affects every member, which is a separate change. The pull request edits the one crate's source and, only when a test needs a crate that is not yet a dev-dependency, that crate's `Cargo.toml`.

### Does the test need Redis or a database?

Only when the failing crate does. `.github/workflows/ci.yml` installs `sqlite3`, `libpq-dev` and `redis-server`, creates `todo.db` and runs the `basics/todo` migrations before `cargo test`, and the agent repeats those steps in its sandbox when the handler under test reaches one of them. A handler that fails on input alone needs none of it.

### What does the agent do when the error does not reproduce?

It stops and reports what it tried: the request it built from the event, the test it wrote, and what the handler returned instead. The result names the gap, such as a header the event did not keep, and opens no pull request.
