For AI agents: the complete documentation index is available at /next/llms.txt, the full documentation bundle is available at /next/llms-full.txt, and this page is available as Markdown at /next/ai/agent-lynx/debugging.md.
AI logo
AI
  • English
  • Logs and Runtime Debugging

    When page inspection reveals an unexpected result, agent-lynx can connect it to console logs, loaded scripts, and live JavaScript values. These provide evidence of where execution stopped and which runtime inputs the code received.

    Trace an Unresponsive Tap to a Runtime Error

    Return to the Tailwind CSS Settings example from page inspection. This time, tapping Ocean does not change the theme. To reproduce the failure, we added a missing-configuration read to the tap handler in a local checkout; the original example does not have this error.

    The commands and outputs below were captured in Lynx Explorer on Android. The agent has already connected to the app and selected the page. $CLIENT_ID is the target app ID returned by list-clients; this page has session ID 2.

    Example conversation6 tool calls
    You

    I tapped Ocean, but the theme did not change. Find out why.

    Agent

    Approach:I will find the Ocean button, start watching error logs, then tap it again to reproduce the problem.

    agent-lynx snapshotOcean button found
    Call
    # Read the current element refs. This excerpt shows the theme controls; @e15 is the Ocean button container.
    agent-lynx snapshot --client "$CLIENT_ID" --session 2
    Output
    @e1 [scroll-view] @(207,450) {scrollable}
    └─ @e2 [view] @(207,460)
       ├─ @e3 [view] @(207,70)
       │  ├─ @e4 [text] "Settings" @(207,59)
       │  └─ @e5 [text] "Manage your account and preferences." @(207,86)
       ├─ @e6 [view] @(207,177)
       │  ├─ @e7 [view] @(207,153)
       │  │  ├─ @e8 [text] "Theme" @(207,143)
       │  │  └─ @e9 [text] "Switch design tokens at runtime via CSS variables." @(207,167)
       │  └─ @e10 [view] @(207,207)
       │     ├─ @e11 [view] @(91,206)
       │     │  └─ @e12 [text] "Dark" @(91,206)
       │     ├─ @e13 [view] @(207,206)
       │     │  └─ @e14 [text] "Light" @(208,206)
       │     └─ @e15 [view] @(324,206)
       │        └─ @e16 [text] "Ocean" @(323,206)
    agent-lynx tap @e15Tap reproduced
    Call
    # Tap the button from the current snapshot while the console watcher is listening, so the capture covers this action.
    agent-lynx tap @e15 --client "$CLIENT_ID" --session 2
    Output
    Tapped @e15 at (324,206). Re-run `agent-lynx snapshot` before using refs again.

    Approach:The background VM threw a TypeError while reading ocean. The stack points to background.js; I will find that loaded script’s ID.

    agent-lynx get-sourcesScript 5 matched
    Call
    # List the scripts in the current background VM. app-service.js is present too; this error points to .lynx/main/background.js.
    agent-lynx get-sources --client "$CLIENT_ID" --session 2
    Output
    [
      {
        "scriptId": "1",
        "url": "file://shared/lynx_core.js"
      },
      {
        "scriptId": "4",
        "url": "file://view3/app-service.js"
      },
      {
        "scriptId": "5",
        "url": "file://view3/.lynx/main/background.js"
      }
    ]
    agent-lynx cdp --method Debugger.getScriptSourceFailing callback found
    Call
    # Read the actual source for script 5, then use jq to extract lines 484–491 of scriptSource around the failing callback.
    agent-lynx cdp --thread background --method Debugger.getScriptSource '{"scriptId":"5"}' --client "$CLIENT_ID" --session 2 | jq -r '.scriptSource | split("\n")[483:491][]'
    Output
            $0: themeNames.map((t)=>/*#__PURE__*/ (0,_lynx_js_react_jsx_dev_runtime__rspack_import_0.jsxDEV)(__snapshot_835da_abf5c_2, {
                    values: [
                        `flex-1 rounded-md py-2 items-center justify-center border ${currentTheme === t ? "bg-primary border-primary" : "bg-secondary border-border"}`,
                        ()=>setCurrentTheme(lynx.__globalProps.themeNames[t]),
                        `text-sm font-medium ${currentTheme === t ? "text-primary-foreground" : "text-secondary-foreground"}`
                    ],
                    $0: t[0].toUpperCase() + t.slice(1)
                }, t, false, {

    Approach:The callback reads lynx.__globalProps.themeNames[t] before calling setCurrentTheme. I will check themeNames in the same background VM.

    The tap reached its handler, which threw a TypeError while reading lynx.__globalProps.themeNames[t]. The current value of themeNames is undefined, so reading its ocean property fails before setCurrentTheme runs.

    This example already gets the theme name from the iteration variable t; restore setCurrentTheme(t). If the application needs host configuration instead, define and supply that field and handle its absence explicitly.

    The log connects the unchanged theme to an exception in the background VM. The script identifies the failing property read, and evaluate checks its current value. The script list includes app-service.js, while this stack points to .lynx/main/background.js; follow the URLs and script IDs returned by the runtime.

    get-console subscribes to runtime logs; it does not guarantee access to past messages. This conversation starts --watch before tapping and ends the capture after two errors arrive. An empty short capture does not mean the page never logged an error.

    Locate an Element's JSX and Event Handler

    A stack trace identifies a location in the running script. A UI source map connects an element on the page to the JSX that created it. Looking up the Ocean button carries the investigation into the local source file.

    This example runs the same bundle in a development client that supports DOM.getOriginalNodeSourceInfo, with UI source maps enabled at build time. $CLIENT_ID selects that client; this page has session ID 1.

    Example conversation3 tool calls
    You

    Which JSX creates the Ocean button? Find its tap handler too.

    Agent

    Approach:I will take a fresh snapshot, select the Ocean button container, and map that element to its source.

    agent-lynx snapshotOcean button found
    Call
    # Refresh the page refs. This excerpt shows the theme controls; @e15 contains the Ocean label.
    agent-lynx snapshot --client "$CLIENT_ID" --session 1
    Output
    @e1 [scroll-view] @(207,450) {scrollable}
    └─ @e2 [view] @(207,460)
       ├─ @e3 [view] @(207,70)
       │  ├─ @e4 [text] "Settings" @(207,59)
       │  └─ @e5 [text] "Manage your account and preferences." @(207,86)
       ├─ @e6 [view] @(207,177)
       │  ├─ @e7 [view] @(207,153)
       │  │  ├─ @e8 [text] "Theme" @(207,143)
       │  │  └─ @e9 [text] "Switch design tokens at runtime via CSS variables." @(207,167)
       │  └─ @e10 [view] @(207,207)
       │     ├─ @e11 [view] @(91,206)
       │     │  └─ @e12 [text] "Dark" @(91,206)
       │     ├─ @e13 [view] @(207,206)
       │     │  └─ @e14 [text] "Light" @(208,206)
       │     └─ @e15 [view] @(324,206)
       │        └─ @e16 [text] "Ocean" @(323,206)

    Approach:The mapping points to a view at App.tsx line 62. I will read the surrounding JSX to find the handler bound to that node.

    Read · examples/tailwindcss/src/App.tsxbindtap found
    Call
    // Read lines 61–80 of the local example checkout. Line 69 contains the failing handler introduced for this reproduction.
    Read examples/tailwindcss/src/App.tsx:61–80
    Output
        61	            {themeNames.map((t) => (
        62	              <view
        63	                key={t}
        64	                className={`flex-1 rounded-md py-2 items-center justify-center border ${
        65	                  currentTheme === t
        66	                    ? "bg-primary border-primary"
        67	                    : "bg-secondary border-border"
        68	                }`}
        69	                bindtap={() => setCurrentTheme(lynx.__globalProps.themeNames[t])}
        70	              >
        71	                <text
        72	                  className={`text-sm font-medium ${
        73	                    currentTheme === t
        74	                      ? "text-primary-foreground"
        75	                      : "text-secondary-foreground"
        76	                  }`}
        77	                >
        78	                  {t[0].toUpperCase() + t.slice(1)}
        79	                </text>
        80	              </view>

    The Ocean button maps to the view at line 62, column 15 of examples/tailwindcss/src/App.tsx, created by themeNames.map. Its bindtap at line 69 binds the handler that reads the missing configuration field identified above.

    get-source-info returns the element's source location. Reading that file reveals the event binding and application logic. A mapped status indicates success; runtime-generated wrappers or pages without the required metadata may not resolve to source locations.

    Keep Runtime Evidence on the Same Target

    A session can contain both background and main VMs. The example's log is tagged background, so the subsequent script request and evaluation target that VM. get-sources lists scripts from the background VM.

    Script IDs and remote object IDs belong to their client, session, and VM. For example, when a log contains an objectId, cdp can inspect its properties through Runtime.getProperties on the same target. After reloading or switching pages, obtain new logs and script IDs before continuing.

    Logs and Runtime Debugging Capabilities

    CapabilityWhat it supports
    Read and follow logsget-console reads console messages with their level, VM thread, and available stack traces. Watch mode follows new messages while an issue is reproduced.
    Identify loaded scriptsget-sources lists script URLs and IDs from the background VM. cdp with Debugger.getScriptSource reads a script's runtime source.
    Locate an element's sourceget-source-info maps an element ref from a fresh snapshot to its source location when UI source-map metadata is available.
    Inspect JavaScript valuesevaluate executes an expression in the background or main VM to inspect live values, await a Promise, or return a remote object for further inspection.
    Open a graphical inspectorinspect prints a URL for inspecting the selected client and session in a graphical interface.
    Send a page protocol requestcdp exposes methods supported by the Lynx CDP implementation, including script source and runtime object inspection.
    Send a host protocol requestapp sends an App protocol request to the selected client. Available methods and parameters depend on the host application.

    Filtering options, output formats, VM selection, and evaluation parameters are covered in the CLI reference. For component props, state, and relationships, continue with ReactLynx components.

    Except as otherwise noted, this work is licensed under a Creative Commons Attribution 4.0 International License, and code samples are licensed under the Apache License 2.0.