SfSkills Domains Docs GitHub

Home / lwc / lwc-debugging-devtools

lwc-debugging-devtools

Use when you need to diagnose live Lightning Web Component behavior in the browser — setting breakpoints, stepping through @wire emits, inspecting component state with the Lightning Component Inspector, reading. NOT for Jest test failures — use `lwc-testing` — and NOT for Apex debug logs, which are — use lwc/common-lwc-runtime-errors.

Open the skill folder on GitHub


LWC Debugging DevTools

Use this skill when an LWC compiles and deploys cleanly but misbehaves at runtime, and the next step is live browser debugging — breakpoints, the component tree inspector, wire network traces, and render profiles — rather than static code review. This skill is about the tooling; specific error-message diagnosis lives in common-lwc-runtime-errors.


Before Starting

Gather this context before touching devtools:


Core Concepts

Debug Mode Is Per User, Not Per Org

Salesforce serves minified LWC bundles by default for performance. Enabling Debug Mode for a specific user replaces the minified bundle with un-minified JavaScript and serves source maps. That means: you can enable Debug Mode for yourself to investigate a ticket without affecting any other user. End users continue to see the fast, minified version. Debug Mode lives in Setup and is also exposed to each user via their own Debug Mode page. It does not live under "Production Settings" — a common hallucination.

Source Maps, Breakpoints, and the Sources Panel

With Debug Mode on and a hard refresh, Chrome DevTools' Sources panel shows the original component files under a virtual path that includes the component namespace and bundle name. You can set breakpoints by clicking the gutter, or by dropping a debugger; statement in the component (remove before commit). The Sources panel is also where you toggle "Pause on caught exceptions" — essential for catching errors that LWS or the framework swallows before they reach your listener. The top of the call stack will usually be your component code; frames lower in the stack belong to the LWC engine and @salesforce/* modules.

The Lightning Component Inspector

The Lightning Component Inspector is a Salesforce-published Chromium extension that adds a panel to DevTools. It shows the component tree for the current page, the @api property values on any selected component, and the current state of each @wire on that component (loading, data, error). It is the fastest way to answer "is the wire emitting at all, and what is it returning?" without writing logging code. It is Chromium-only; there is no Firefox equivalent.

Logging Under Lightning Web Security

LWS wraps many platform objects in membrane Proxies so that component code cannot reach into privileged internals. console.log(obj) with a Proxy-wrapped object often shows the handle, not the traversed contents. The workaround is to force a plain JSON copy: console.log(JSON.parse(JSON.stringify(obj))) or, when the structure is known to be clonable, console.log(structuredClone(obj)). Non-JSON-clonable values (functions, Map, Set) still need ad-hoc unwrapping.

Wire Traffic on the Network Panel

UI API wire adapters (getRecord, getRelatedListRecords, the GraphQL adapter) hit /services/data/vXX.X/ui-api/*. Filter the Network panel by /ui-api/ to see exactly which wires fire, their payload shape, and any 4xx/5xx. If a wire "never emits," there are two common causes: a reactive $variable is still undefined, so the adapter was never activated; or the adapter ran and the response was cached with undefined data (no fields requested).

Render Profiling and Mobile

The Performance panel captures long tasks, render frames, and script execution for the LWC runtime. For mobile debugging, the Salesforce Mobile app exposes a debug bridge that lets desktop Chrome DevTools attach to the in-app webview; pair this with Debug Mode for the mobile user.


Common Patterns

Pattern 1: Prove the Wire Is Firing

When to use: @wire appears not to emit, component shows no data.

How it works: Enable Debug Mode, hard-refresh, open Network and filter by /ui-api/. Place a breakpoint on the first line of the wire handler function. Reproduce. If the breakpoint never hits and no network call fires, the reactive parameter is undefined; inspect the class property feeding $recordId in the Inspector panel. If the breakpoint hits with data: undefined, error: undefined, that is the normal first emission — step and watch for the second emission.

Why not the alternative: console.log alone tells you nothing about whether the adapter was activated at all.

Pattern 2: Capture a Silent Render Failure

When to use: Component renders blank in production, works in dev sandbox.

How it works: Confirm Debug Mode is enabled for the prod user (this is the frequent miss), hard-refresh, open Sources, enable "Pause on exceptions" and "Pause on caught exceptions." Reproduce. If a throw is caught by LWS or the framework error boundary, the debugger pauses at the origin so you can read the real message instead of a swallowed one. Use the Inspector to confirm which child component is actually failing.

Why not the alternative: Relying on the browser console alone misses errors that LWS silently wraps or that a parent errorCallback swallows.

Pattern 3: Readable Logging Under LWS

When to use: You need to dump component state and plain console.log shows a Proxy handle.

How it works: console.log('state', JSON.parse(JSON.stringify(this.account))); — this materializes the wrapped object into a plain JSON tree the console can expand. For shapes that include Map/Set or circular refs, log individual fields instead of the whole object.

Why not the alternative: console.log(this.account) in LWS shows Proxy {} or similar, making the log useless for diagnosing data shape.


Decision Guidance

SymptomStart HereWhy
Component renders blankConfirm Debug Mode is on, open Sources with pause-on-exceptions, scan for thrown errorsMany render failures are swallowed by framework error boundaries or LWS
@wire never emitsNetwork panel filtered by /ui-api/, breakpoint at top of wire handlerDistinguishes "adapter never activated" from "adapter returned empty"
Works in dev, fails in prodCheck Debug Mode status in the prod user; check CSP/Experience Cloud contextMinified code without source maps is the single biggest "I can't see anything" cause
Console logs show Proxy handlesWrap with JSON.parse(JSON.stringify(obj)) or log individual fieldsLWS proxies block the default console traversal
Render feels slowPerformance panel, record a 10s profile around the interactionGives per-frame render cost and long-task attribution
Bug only reproduces on mobileEnable Debug Mode for the mobile user, attach desktop Chrome via mobile debug bridgeNo parity tool exists inside the mobile app itself

  1. Enable Debug Mode for your user — Setup → Debug Mode (or the per-user Debug Mode page). Confirm the badge appears in the app nav.
  2. Hard-refresh and confirm un-minified JS — DevTools → Sources → search for your bundle filename. You should see readable code, not a single-line minified blob.
  3. Install the Lightning Component Inspector — Chromium extension; reload the page; confirm the "Lightning" panel appears in DevTools.
  4. Reproduce with Pause on Exceptions on — toggle both caught and uncaught pausing; reproduce the user action; let the debugger catch any thrown error.
  5. Inspect component state and wire responses — use the Inspector to read @api values and wire state; use the Network panel filter /ui-api/ to see raw wire payloads.
  6. Capture a Performance profile if perf-related — record during the slow interaction; inspect long tasks and render frames.
  7. Disable Debug Mode when finished — Debug Mode noticeably degrades perceived performance; leaving it on in production pollutes analytics and user experience.

Review Checklist


Salesforce-Specific Gotchas

  1. Debug Mode is per user, not per org — enabling it for yourself does not help an end user who is also seeing the bug; either enable it for their user, or reproduce under your own user.
  2. console.log(this.record) under LWS prints a Proxy handle — looks like the object is empty; it is not. Unwrap with JSON.parse(JSON.stringify(...)).
  3. Breakpoints are meaningless without source maps — without Debug Mode, the Sources panel shows minified code and your breakpoints land on the wrong line or a wrapper.
  4. The Lightning Component Inspector is Chromium-only — Firefox users have no equivalent; switch to Chrome/Edge/Brave.
  5. renderedCallback breakpoints fire many times — they run after every render. Use conditional breakpoints on a specific prop value or log-points to avoid storming the debugger.
  6. Experience Cloud CSP is stricter than LEX — "works in LEX, fails in Experience Cloud" is often a Content Security Policy issue surfacing on a different surface.
  7. Leaving Debug Mode on globally is an anti-pattern — real users see degraded perf, and analytics get skewed; always turn it off when the investigation ends.

Output Artifacts

ArtifactDescription
Diagnosis pathOrdered devtools steps from symptom to root cause
Wire network traceFiltered /ui-api/ requests with payload and timing
Inspector captureComponent tree state, @api values, @wire state for the failing component
Performance profile summaryLong tasks, render frames, attributable scripts
Checker reportOutput from scripts/check_lwc_debugging_devtools.py

Package files