All jobs

Turn Sentry Errors Into Fix Pull Requests for a Nuxt App

Yes. A Sentry alert starts the run; the agent maps the frames to your Nuxt pages and composables, reproduces the error with Vitest and opens a pull request.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads the alert payload after the prompt, then asks Sentry for the issue and its latest event through the connection: the error message, whether it was thrown on the server during rendering or in the browser after hydration, the page URL, and the in-app frames. In a Nuxt app those two cases point at different code, so it settles that first. A server-side frame names a page's top-level await or a composable; a browser frame names a component method or a computed.

In a Nuxt app like nuxt/movies it then reads the project in its clone. package.json runs nuxt-nightly at 4.6.0 with compatibilityVersion: 5 in nuxt.config.ts, pnpm 11.1.2 and Node ^24 under devEngines, Vitest ^4.1.11 with @nuxt/test-utils, @vue/test-utils and happy-dom, and Playwright for tests/e2e. Data comes from app/composables/tmdb.ts: fetchTMDB calls $fetch against https://movies-proxy.vercel.app/tmdb, keeps one promise per request hash in an LRUCache and the answer in useState, and deletes the cache entry when the request rejects. getMedia throws createError with status 404 for ids in its blocked set; listMedia, getRecommendations and searchShows filter those ids out of results. app/pages/[type]/[id].vue awaits getMedia and getRecommendations in a Promise.all at the top of <script setup> and then passes item.poster_path to $img inside useHead; app/pages/person/[id].vue does the same with getPerson. app/composables/item.ts reads item.videos?.results?.find for the trailer, and app/composables/utils.ts formats dates, runtimes and vote counts. app/error.vue renders the thrown error for anything that is not a 404.

The test goes where the repository already keeps them. vitest.config.ts includes **/composables/**/*.test.ts, **/components/**/*.test.ts and tests/unit, and the existing files use the .nuxt.test.ts suffix so @nuxt/test-utils runs them in the Nuxt environment, with mockMedia and mockPerson from tests/unit/mocks.ts building fixtures. The agent writes a test next to the composable or component the frames name, feeds it the shape the Sentry event implies, such as a media item with no poster_path or a videos object with no results, and runs pnpm vitest run <file>. The failing output is kept as the reproduction.

Then it fixes the cause, in the composable, the page or the component, reruns the test until it passes, and runs the three commands the tests-unit.yml workflow runs: pnpm run test:unit, pnpm run lint with the antfu ESLint config, and pnpm run typecheck through nuxt typecheck. A fix that changes a page's useHead or a v-if is checked against the Playwright specs in tests/e2e when the browsers install in the sandbox. The agent does not add a catch that turns a failed TMDB request into an empty page; where the right behaviour is a 404, it throws createError as getMedia already does for blocked ids.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "A Sentry alert fired for this Nuxt app; its payload follows this prompt. Use the Sentry connection to read the issue, its latest event, whether it happened on the server or in the browser, and the in-app stack frames. Match the frames to the pages under app/pages, the composables in app/composables (start with tmdb.ts and item.ts) and the components under app/components. Write a Vitest test with the .nuxt.test.ts suffix next to the failing composable or component, using the mocks in tests/unit/mocks.ts, that reproduces the error, then fix the cause until `pnpm run test:unit` passes. Install with pnpm, then run `pnpm run lint` and `pnpm run typecheck`. Open a pull request that links the Sentry issue, quotes the frames and the failing test output, and explains the cause. Change nothing unrelated to this error.\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

You get a pull request whose diff is the fix in one page, composable or component plus one new .nuxt.test.ts file beside it. The description links the Sentry issue, says whether the error was server-rendered or client-side, quotes the frames it placed, shows the test failing before and passing after, and lists the test:unit, lint and typecheck commands with their summary lines.

The session's transcript keeps every Sentry call, every command and its output, and every file read, so the reviewer can see that the typecheck passed rather than read a sentence saying so. The run.completed webhook carries the agent's final message as data.result and a session_url for the rest.

Before merging, the reviewer checks that the test reproduces the reported error and not a neighbouring one, that a change in tmdb.ts still deletes the cached promise when a request rejects so a transient failure is not pinned for the cache's lifetime, and that the page still renders the 404 path for blocked ids. Follow-up messages to the same session change the branch in place.

Run it on every Sentry issue alert

Create an alert rule in the Sentry project with a webhook action and point it at a handler on your server. The handler adds the alert's JSON after this prompt, sends the request with the issue id as Idempotency-Key, and returns. A resent alert returns the same run, so one issue never becomes two pull requests.

Set a webhook URL on the key and Rush POSTs run.completed with session_url when the pull request is ready; your handler can comment the link on the Sentry issue. Or have that handler call a webhook trigger on an automation in the Project with this prompt: it forwards the alert's JSON as the body with the trigger's secret as Authorization: Bearer, because Sentry signs its own webhooks and cannot send that header. The body becomes the event text after the prompt, and max_runs_per_hour caps an issue that keeps firing.

The use case this job follows, with its automation and trigger: Fix a bug from an alert.

Why run it on Rush?

Nuxt errors split into server-render and browser cases, and reproducing either by hand means guessing which API response the page saw. The agent reads that from the Sentry event, builds the fixture with the repository's own mocks and runs the project's unit, lint and typecheck commands in a sandbox with the right pnpm and Node, while your own checkout stays untouched.

The pull request brings the evidence: a test that failed, the same test passing, and a transcript of each command. Each issue is its own run, so a release that broke the detail page and the person page at once produces two separate branches, worked in parallel up to the key's max_concurrent limit, each small enough to review in a few minutes.

Frequently asked questions

Does it need the TMDB proxy to run the tests?

No. The unit tests mock the composable's input with mockMedia and mockPerson from tests/unit/mocks.ts, so they do not call https://movies-proxy.vercel.app. The Playwright specs in tests/e2e do reach the proxy, and the agent runs them only when the fix touches a page they cover.

How does it tell a server error from a browser error?

The Sentry event says which SDK sent it and carries the request or the browser context. A frame in a page's <script setup> await or in a composable called during render is server-side under Nuxt's SSR; a frame in a click handler or a watch is client-side. The pull request states which it was, because the fix and the test differ.

Will it change nuxt.config.ts?

Not for a code error. The config sets the proxy base URL, the i18n locales and the html-validator rules, and none of those cause an exception in a page. If the frames point at a module option, the agent says so in the pull request and keeps the change to that option.

The frames point at a nightly Nuxt build. Can it still fix my code?

The agent fixes the code in app/, not the framework. When the top in-app frame is inside nuxt-nightly itself, it says so and proposes the smallest change on your side that avoids the path, or opens no pull request and reports what it found.