Skip to main content
Blog

From a Real User Error to a Fix PR in 8 Minutes: RUM × AI SRE

A user hit three frontend errors while creating a monitoring rule. RUM preserved the session, version, and SourceMap stack; AI SRE located the right repository, made a one-line fix, and opened a PR.

Flashcat Engineering

From a Real User Error to a Fix PR in 8 Minutes: RUM × AI SRE

On July 15, a user opened the monitoring rule creation page. While they were building a rule, the browser raised the same exception three times:

TypeError: Cannot read properties of undefined (reading 'filter')

All three errors happened within half a minute. A user may never file a ticket for a localized UI problem like this, and an engineer cannot reliably reproduce it from “something on the page felt wrong.”

The RUM SDK running in the page had already preserved the scene.

RUM stands for Real User Monitoring. Instead of checking whether a page works in a test environment, it records what happens while real people use a web or mobile application. When an error occurs, RUM can connect it to the page, release, device, and surrounding user journey, then group similar samples into an Issue.

This Issue told us that the error was concentrated on the monitoring rule creation page. The current sample affected one session, occurred three times, and came from the same production release. The session timeline also preserved the page views leading up to the failure.

That is the first layer of value RUM provides. It does not rush to guess the cause. It turns an exception scattered inside a browser console into an online problem that can be queried, grouped, and investigated.

SourceMap brought the production error back to source

Frontend bundles are normally built and minified before deployment. Without a SourceMap, a browser stack often points to a location such as index-q2_vQxih.js:134:36624. An engineer still has to work out which source file and function produced that line.

A SourceMap preserves the relationship between minified output and the files used during development. When the SourceMap uploaded for a release matches the deployed bundle, RUM can restore the production stack to the original file, function, and line number.

For this Issue, RUM restored the top stack frame to:

src/Packages/monit/pages/rule/add/content.tsx:322:16

The calling frame was restored to content.tsx:287:12. Expanding the stack showed the exact source line:

if (queries.filter((i) => i.expr).length === 0) return false;
SourceMap restores the minified production stack to the source file, line number, and code

The screenshot has been cropped to remove Issue, application, user, and session identifiers.

The problem was no longer “a call to filter failed somewhere inside a minified bundle.” An engineer could now see that validateQueryStep called .filter() on queries while validating the alert query configuration.

But knowing which line failed is not the same as knowing why it failed. Why was queries undefined? Which repository owned this file? Should the fix go into the frontend shell or the monitoring micro frontend? Those questions still had to be answered.

RUM saw the context; SRE automation handed it to AI SRE

In our setup, a RUM Issue enters the Flashduty Incident response flow and then triggers an SRE automation.

AI SRE is concerned with finding, diagnosing, and recovering from online problems faster while using automation to remove repetitive work. The automation defines the trigger, injects RUM context, selects the investigation steps and tools, and controls how far AI SRE is allowed to act.

AI SRE did not receive a single error string. It received the full evidence set: error type, occurrence count, page URL, release version, session distribution, and the SourceMap stack.

This investigation also had a practical complication. The application-level mapping initially pointed to the frontend shell, foundation-app. But the failing page lived at /monit/rule/add. By combining the route with the restored source path, AI SRE continued into the monitoring micro frontend and found the repository that actually owned the code instead of searching blindly inside the shell.

That distinction matters in large frontend applications. A shell may host several independent micro frontends. Knowing which application emitted an error is not enough; the page route, SourceMap path, and repository mapping have to be used together to identify the code that should change.

The root cause was hidden in form initialization

The SourceMap context was roughly:

const { rule_configs } = allValues;
if (!rule_configs) return false;

const {
  check_threshold,
  check_anydata,
  check_nodata,
  queries,
} = rule_configs;

if (queries.filter((i) => i.expr).length === 0) return false;

The code checked that rule_configs existed, but assumed that queries inside it was always an array. During the initial form validation, rule_configs had already been created while the query list had not finished initializing. At that point, queries could still be undefined.

This also explained why the error appeared repeatedly in the same visit: every validation pass could reach the same line again.

The fix did not require an API change or a form rewrite. The “no query configured yet” state only needed to fail validation without throwing:

- if (queries.filter((i) => i.expr).length === 0) return false;
+ if ((queries ?? []).filter((i) => i.expr).length === 0) return false;

It was a one-line change. When queries exists, the behavior is unchanged. Before initialization completes, the empty array makes validation return false instead of raising an exception.

Eight minutes after the final error, the fix reached the main branch

The Issue left a clear timeline:

  • RUM recorded the final error sample.
  • About four minutes later, the defensive fix for queries.filter(...) was committed.
  • About eight minutes after the final sample, the fix PR was merged into the main branch.

The PR described the production error, service and release, SourceMap line, root cause, and one-line diff. It was also marked as Agent-generated.

“Automated remediation” does not mean that AI bypasses the engineering process and deploys directly. AI SRE can read the evidence, modify code, and create a PR. The team still decides whether to merge and when to release. In this case, the fix was reviewed and merged. The last RUM error sample occurred just before that merge; over the following seven days, no new sample of the same error appeared.

A week later, we replayed the same Issue through AI SRE. It read the RUM evidence again, followed the route and SourceMap into the monitoring micro frontend, and confirmed that the protection was already present on the main branch. It correctly avoided producing a duplicate change. For SRE work, avoiding redundant remediation matters just as much as avoiding a missed fix.

Not every RUM Issue should reach the code repository

Another Issue, fetchError · Network request failed, triggered the same automation. It affected a single mobile session, occurred once, produced no cluster of similar errors, and did not contain enough page or stack evidence.

AI SRE did not change code merely to complete the task. It recorded the current assessment and the missing evidence: observe the signature first, then reopen the investigation if it repeats or begins affecting more sessions.

AI SRE records a no-code-change verdict for a one-off mobile network failure

Together, the two Issues show why the automation matters. When the evidence points to a source defect and the change boundary is clear, the investigation can continue to a PR. When the evidence is weak or the problem looks environmental, the correct action is to stop—not to manufacture an uncertain code change.

RUM and AI SRE form a closed loop when they are connected

RUM is useful on its own. It tells a team what real users experienced, how many sessions were affected, which releases were involved, and how Session data and SourceMaps can reduce reproduction and triage time.

AI SRE builds on that evidence. It continues with impact assessment, repository location, source analysis, and controlled action. SRE automation connects the two: it defines which Issues trigger, which context is injected, which tools are available, whether a PR may be opened, and where human confirmation is required.

Engineers keep Review, merge, and release authority. After a release, RUM continues watching the new version for the same error.

RUM and AI SRE connected by automation, from real-user context to remediation, observation, or human handoff

RUM provides real-user evidence. Automation controls the trigger, context, investigation steps, and permissions. AI SRE performs the investigation and controlled actions. Engineers retain Review and release authority.

If you want to run this loop with your own application

If you are not using RUM yet, start with one important frontend application. In addition to collecting errors, configure release, environment, page, and session context, and upload the matching SourceMap with every release.

The first milestone does not need to be ambitious. Once an Issue can answer “what failed, on which page, in which release and sessions, and at which source line,” RUM is already reducing investigation time.

Next, map applications and pages to their code repositories. Give AI SRE controlled access to read RUM evidence, inspect source, and create a PR. A good first replay is an older Issue that recurred several times and whose SourceMap already points to business code.

A useful replay does not have to produce a PR. It may conclude that the evidence is insufficient, that the issue is already fixed, or that continued observation is the right action. The real goal is evidence at every decision, an explicit boundary around code changes, and engineers retaining control of merge and release.

If you have a frontend Issue that has been difficult to reproduce, bring it to a RUM × AI SRE replay. Start with the real-user evidence and see whether it can reach a fix PR that an engineer can Review.

Related articles