BugMojoBugMojoBugMojo
FeaturesPricingBlogHelpAbout
Add to ChromeLog inGet started
BugMojoBugMojo

Bug reports that actually help fix bugs — capture, replay, share.

A product of Softech Infra.

Product

  • Features
  • Pricing
  • Browser extension
  • Get started
  • Log in

Resources

  • Help & guides
  • Blog
  • Compare
  • Glossary

Company

  • About
  • Contact
  • Security
  • Privacy
  • Terms
  • Sitemap
© 2026 BugMojo. All rights reserved.
AllGuidesEngineeringPlaybooksCompareGlossaryAlternativesBy roleBug tracking by framework
  1. Home
  2. Blog
  3. Guides
  4. How to Debug JavaScript Errors in Production (Without Guessing)
Guides

How to Debug JavaScript Errors in Production (Without Guessing)

A minified stack trace is a riddle until you add source maps. Pair them with a console, network, and session replay, and you stop guessing: reproduce from the real user session, isolate the cause, ship the fix.

Hrishikesh BaidyaHrishikesh Baidya·Jun 26, 2026·10 min read
Guides
Isometric line-art of a session replay timeline, a console error, and a source-mapped stack trace feeding an AI debugging agent, in lime on near-black
TL;DR

Debugging JavaScript errors in production stops being guesswork when you capture the real failure instead of inferring it. The method: (1) de-minify the stack trace with source maps so main.4f2a.js:1:88213 resolves to a real file and line; (2) capture the console, network, and a session replay on one timeline; (3) reproduce from the user's session; (4) isolate the cause; (5) ship the fix. Log-spelunking guesses at the steps. Replay-driven debugging makes the reproduction the artifact.

An error count ticks up in your dashboard. The stack trace reads t is not a function at main.4f2a.js:1:88213. You cannot reproduce it locally, the user is gone, and the logs show a dozen unrelated lines around the crash. So you start guessing: add a log, redeploy, wait, refresh, repeat. This is log-spelunking, and it is the default way most teams debug production JavaScript. It is slow, and it is unreliable because you are reconstructing a failure you never actually saw.

There is a repeatable alternative. Capture the real failing session, resolve the trace through source maps, reproduce from the recording, isolate the cause, and ship. This guide walks that method end to end and contrasts the two approaches honestly. The argument for replay-driven debugging is not aesthetic. The 2025 Stack Overflow Developer Survey found that 66% of developers name "AI solutions that are almost right, but not quite" as their top frustration, and 45.2% say debugging AI-generated code is more time-consuming than debugging human-written code. Plausible-looking is not the same as correct. The fix is to debug from evidence, not from a story you tell yourself about what happened.

How do you debug a JavaScript error in production without guessing?

Resolve the minified stack trace with source maps so it points to real files and lines. Capture the console, network requests, and a session replay together on one timeline. Reproduce the failure by replaying the user's session rather than inferring steps. Isolate the cause against the last deploy, then ship and verify the fix. Capture first, diagnose second.

The five steps are ordered deliberately: capture, resolve, reproduce, isolate, ship. The expensive mistake is reversing capture and diagnose. If you start writing a fix before you have reproduced the failure, you are patching a symptom you guessed at. Every step below produces an artifact that the next step consumes, and the same artifacts hand off cleanly to an AI agent at the end.

Step 1: Resolve the stack trace with source maps

A production bundle is minified, so the browser sees a.js:1:18327, not checkout.ts:42. A source map is a JSON file that maps the transformed code back to your original source. Per MDN, browsers locate it via the SourceMap HTTP response header or a sourceMappingURL annotation in the generated file. That mapping is the mechanism that turns a meaningless column offset into a real function, file, and line.

Chrome DevTools can de-minify a production trace once you enable JavaScript source maps under Settings > Preferences > Sources. The Console then links to your authored files, and when execution pauses at a breakpoint the Call Stack shows original filenames. This is not a niche capability anymore: in March 2025 AWS added JavaScript source map support to CloudWatch RUM, converting minified production traces into readable file, line, and column locations. Mapping minified errors back to source is table stakes across monitoring vendors now, not a nice-to-have.

upload-sourcemaps.shbash
# Generate source maps at build time, but do NOT serve them publicly.
# Vite / Rollup
vite build --sourcemap hidden   # emits .map files + sourceMappingURL stripped from bundle

# A 'hidden' source map produces the .map file for your tooling
# without the sourceMappingURL=... comment in the shipped JS,
# so the public bundle never advertises where the map lives.

# Upload the maps to your error/capture tool over an authenticated channel,
# then delete them from the public web root before deploy:
curl -sf -H "Authorization: Bearer $TOKEN" \
  -F "release=$GIT_SHA" \
  -F "sourcemap=@dist/assets/index.4f2a.js.map" \
  https://your-tool.example.com/api/sourcemaps

rm dist/assets/*.map   # readable traces for your team; no source for the public
Watch out

Do not ship .map files to your public web root. A publicly served source map hands your original source, comments, and sometimes secrets to anyone who opens DevTools. Generate maps at build time, upload them to your monitoring or capture tool through an authenticated channel, and withhold or restrict the public copy. Review build output for hardcoded credentials before every deploy.

Step 2: Capture console, network, and a replay together

A resolved stack trace tells you where the code threw. It does not tell you why. For that you need the state at the moment of failure: what the console logged just before, what network response came back malformed, and what the user actually clicked. The problem is that those three signals normally live in three different places and disappear when the tab closes.

This is where session replay changes the loop. rrweb (around 19.8k GitHub stars) records the DOM, DOM mutations, and user interactions as a stream of JSON events rather than as video. The recording stays small enough to attach to a bug report, and because it is structured DOM rather than pixels, you can inspect the live DOM at any point on the timeline. Align that replay with the console errors and the network waterfall and you have the full picture of one failing session in a single artifact.

FeatureLog-spelunkingReplay-driven (rrweb)BugMojo
Works with zero added tooling✓——
Source-mapped stack trace in contextmanualpartial✓
DOM + console + network on one timeline—✓✓
Reproduction travels with the ticket—✓✓
Mature production error aggregation & alertingpartialpartialearly
Failing session exposed to an AI agent over MCP——✓
Honest two-sided view. Log-spelunking is universally available and needs no setup; replay-driven debugging needs capture in place but removes the guessing. BugMojo is early on production aggregation and owns the agent-handoff row.

Step 3: Reproduce from the user session

"Cannot reproduce" is the phrase that kills production bugs. It is also an artifact of log-spelunking: you cannot reproduce because you are guessing at the steps. Replay-driven debugging removes the problem by definition, because the reproduction is the recording. You scrub the timeline to the moment the console error fired, watch the exact clicks and form inputs that preceded it, and inspect the DOM state and the network response that the code choked on. There is nothing to reconstruct.

Concretely: open the replay, find the red console entry on the timeline, step back a few hundred milliseconds, and read the network request that resolved just before. Nine times out of ten the malformed payload, the unexpected null, or the race between two requests is sitting right there. You have now reproduced the failure without ever asking the user "what were you doing?"

Key takeaway

The difference between the two methods is the order of operations. Log-spelunking diagnoses first and reproduces last, often never. Replay-driven debugging reproduces first by capturing the session, then diagnoses from the recording. When the reproduction is the artifact, "cannot reproduce" stops being a valid ticket resolution.

Step 4: Isolate the cause

With a reproducible failure in hand, isolation is mechanical. Start with the question that resolves most production incidents: is this a regression? Check the last deploy against the first timestamp the error appeared. If the error started within minutes of a release, your suspect list is that diff, not the entire codebase. Next, confirm the blast radius from the captured metadata: which browser, which version, which route. An error that only reproduces in one browser engine narrows the cause to an API or syntax difference; an error scoped to one route narrows it to that route's code path.

From the source-mapped trace you already know the throwing line. From the network capture you know the input that reached it. The cause is the intersection: the line of original source that received an input it did not handle. Set a conditional breakpoint there in DevTools, replay the captured input, and watch it break in your own debugger. That is isolation complete.

Step 5: Ship the fix (and hand the repro to an agent)

Here is where most production-debugging guides stop: a human reads the source-mapped trace, writes the patch, and ships. That assumes a person is sitting in front of the browser cross-referencing the replay, the console, and the trace by hand. The artifacts you captured in steps 1 through 4 are more useful than that, because they are structured, and structured failure data is exactly what an AI coding agent can consume.

When the rrweb replay, the console logs, the network requests, and the source-mapped stack trace are exposed as structured context over an MCP server, an agent such as Claude Code or Cursor can read the full reproduction and draft the fix without a human re-tracing the steps. The agent sees the failing line in your real source, the network response that triggered it, and the user actions that led there. This is the one thing the existing tools do not do: every error monitor and replay product stops at "a human reads the trace." None turn the reproduction into machine-readable context for an autonomous agent.

It also matters because of trust. The same 2025 Stack Overflow survey reports that 46% of developers distrust the accuracy of AI-tool output (26.1% somewhat distrust plus 19.6% highly distrust), while only about 3% highly trust it. The practical takeaway is direct: an agent's proposed fix should be grounded in a captured reproduction, not generated from a guess. Feed the agent the real failing session and its output stops being "almost right, but not quite."

2025 Stack Overflow survey: why AI fixes need real reproductions
Frustrated by AI 'almost right, but not quite'
66% of developers
Distrust AI tool accuracy (somewhat + highly)
46% of developers
Debugging AI code is more time-consuming
45.2% of developers
Highly trust AI tool accuracy
3% of developers
Source: Stack Overflow 2025 Developer Survey (AI section)

Copy-paste production triage checklist

Run this top to bottom on every production JavaScript error. The first half is capture; the second half is diagnose. Do them in that order. The contrast to keep in mind: a log-spelunking pass jumps straight to step 6 and works backward through guesses, while a replay-driven pass completes steps 1 through 5 first so step 6 reasons from evidence.

  • 1. Capture the error string + de-minified trace. Resolve main.x.js:1:NNNN to a real file and line via source maps before reading anything else.
  • 2. Confirm the environment. Record browser, browser version, OS, and the exact route or URL where it fired.
  • 3. Pull console state at failure. Capture the console entries immediately before and at the throw, not just the error itself.
  • 4. Pull network state at failure. Capture the request and response that resolved just before the error, including status and payload.
  • 5. Attach a session replay. Include the rrweb recording so the reproduction travels with the ticket and the next person does not start from zero.
  • 6. Reproduce from the replay. Scrub to the error, watch the preceding user actions, confirm you can trigger it.
  • 7. Check for regression. Compare the first-seen timestamp against the last deploy; if they line up, suspect the diff.
  • 8. Assign severity. Scope the blast radius (one user, one browser, all users) and prioritize accordingly.
  • 9. Only now write the fix. Or hand the captured bundle to an AI agent over MCP and review the patch it drafts from the real reproduction.
Common mistake

The classic mistake is diagnosing before reproducing. You read a stack trace, form a theory, write a patch, and redeploy to "see if that fixes it" without ever watching the failure happen. That is log-spelunking with extra steps. Capture the session first. If you cannot reproduce from your evidence, you do not yet understand the bug well enough to fix it.

A production stack trace is half the story. The source map gives you the line; the replay, console, and network give you the why. Capture all four and the fix stops being a guess.
BugMojo engineering
⁓ ⁓ ⁓
Capture the failing session, not just the stack trace

Install the free BugMojo extension to capture the rrweb replay, console logs, network requests, and a source-mapped stack trace as one shareable artifact — then let an AI agent read the real reproduction over MCP and draft the fix. No project setup required.

Install the extension

Frequently asked questions

Frequently asked questions

Sources

  1. Stack Overflow 2025 Developer Survey — AI sentiment, trust, and top frustrations with AI-generated code — Stack Overflow (2025)
  2. rrweb — record and replay the web, capturing DOM and interactions as JSON events (GitHub repo) — rrweb-io (2025)
  3. Debug your original code instead of deployed with source maps — Chrome for Developers (Google) (2024)
  4. Source map — Glossary (definition and how browsers locate maps) — MDN Web Docs (Mozilla) (2025-12-15)
  5. SourceMap header — HTTP reference — MDN Web Docs (Mozilla) (2025-11-21)
  6. CloudWatch RUM now supports JavaScript source maps for easier error debugging — Amazon Web Services (2025-03)
Share:
Hrishikesh Baidya
Hrishikesh Baidya· Chief Technology Officer

Hrishikesh Baidya is the CTO at Softech Infra. He is drawn to architecture that is invisible — systems that simply work — and leads the engineering behind BugMojo.

On this page

  • How do you debug a JavaScript error in production without guessing?
  • Step 1: Resolve the stack trace with source maps
  • Step 2: Capture console, network, and a replay together
  • Step 3: Reproduce from the user session
  • Step 4: Isolate the cause
  • Step 5: Ship the fix (and hand the repro to an agent)
  • Copy-paste production triage checklist

Get bug-tracking insights, weekly.

Engineering deep-dives, QA playbooks, and honest tool comparisons. No spam — unsubscribe in one click.