name: fuchsia-debugger description: Use fx debug cli to debug test failures.

Overview

fx debug cli is a machine-readable, agent-friendly interface to zxdb. It uses the Debug Adapter Protocol (DAP) to enable turn-based interactions that agents are already accustomed to and possess knowledge of. Unlike traditional console-based debuggers, fx debug cli exposes a stateless command-line frontend that issues request-response style commands to the backend, allowing agents to send and receive structured JSON as input and output.

fx debug cli integrates with fx test to allow automatic pausing during test failures, which allows Agents to inspect the state and diagnose the failure.


Testing Workflow

This mode delegates the management of the debugging session to the testing framework. The framework automatically starts the zxdb-daemon process and connects to the active target.

Step 1: Start the Test in the Background

Run fx test with the --agent-debugging-mode flag. Execute this command asynchronously in the background so you can proceed with other work while observing the output:

fx test <test_suite_name> --agent-debugging-mode

Note: This automatically starts the zxdb-daemon background process, which begins listening for messages sent via fx debug cli.

Step 2: Poll for Target Transitions

Begin polling the active daemon process for events. Start with last_seen_seq: 0 and increment the sequence number as events are received:

fx debug cli --json '{"command": "wait-for-event", "last_seen_seq": 0, "timeout": 10}'

[!NOTE] Socket Startup Delay: The background daemon may take 1-2 seconds to initialize and bind the listening socket after fx test begins. If the initial command fails with Daemon socket not found, wait briefly and retry.

Example wait-for-event Response (Test Failure / Breakpoint):

{
  "success": true,
  "events": [
    {
      "seq": 1,
      "event": "stopped",
      "body": {
        "threadId": 1,
        "reason": "breakpoint"
      }
    }
  ]
}

[!WARNING] Thread ID Key Casing Mapping Pitfall: Output events returned by wait-for-event use camelCase keys (e.g. "threadId": 1). However, subsequent request commands (such as stackTrace, continue, or pause) strictly require snake_case parameters (e.g. "thread_id": 1). Always map "threadId" to "thread_id" when programmatically invoking requests.

Simultaneously, monitor the output and status of the background fx test task.

Step 3: Handle Execution Scenarios

Depending on the status of the test run, handle one of the following scenarios:

Scenario A: Test Failure (Debugger Suspended)

If wait-for-event returns a "stopped" event, it indicates a test failure or breakpoint hit. Perform diagnostics:

  1. Query Session State: Retrieve all threads and processes active in the session to identify the failing thread:

    fx debug cli --json '{"command": "get-state"}'
    

    Example Response:

    {
      "success": true,
      "body": {
        "threads": [
          { "id": 1, "name": "initial-thread" }
        ],
        "processes": { "12345": "my_test_binary" }
      }
    }
    

    Note: In the get-state thread list representation, the key is "id". Map this value to the "thread_id" parameter in subsequent requests.

  2. Retrieve Stack Trace: Get the stack trace for the suspended thread_id to pinpoint the failure location:

    fx debug cli --json '{"command": "stackTrace", "thread_id": 1}'
    

    Example Response:

    {
      "success": true,
      "body": {
        "stackFrames": [
          {
            "id": 0,
            "name": "my_test_function",
            "source": {
              "name": "main_test.cc",
              "path": "/src/main_test.cc"
            },
            "line": 42,
            "column": 1
          }
        ],
        "totalFrames": 1
      }
    }
    
  3. Teardown Session: Once diagnostics are complete, terminate the debugging session. This detaches from targets and lets the background test runner exit cleanly:

    fx debug cli --json '{"command": "stop"}'
    

Scenario B: Clean Pass (All Tests Succeed)

If all tests pass cleanly, the background fx test task will complete successfully, exiting with status code 0 and summarizing FAILED: 0 in its output.

  • Edge Case: Poll Connection Failures: Since fx test automatically reaps the background daemon process on a clean exit, any active, blocking wait-for-event command will terminate abruptly with a connection error (e.g., connection refused or closed socket).
  • Action: If wait-for-event returns a connection failure, check the status of the background fx test task. If it completed successfully (exit code 0), treat this as a successful clean pass, print a success message, and exit. No manual "stop" command or teardown is required.

JSON Request Reference

All commands are sent as serialized JSON payloads to fx debug cli --json '<payload>'.

ActionCommand Input Payload
Wait for Event{"command": "wait-for-event", "last_seen_seq": <seq>, "timeout": <secs>}
Get State{"command": "get-state"}
List Threads{"command": "threads"}
Attach Process{"command": "attach", "filter": "<name_or_pid>"}
Detach Process{"command": "detach", "pid": <pid>} or {"command": "detach", "all": true}
Get Stack Trace{"command": "stackTrace", "thread_id": <thread_id>}
Continue Thread{"command": "continue", "thread_id": <thread_id>}
Pause Thread{"command": "pause", "thread_id": <thread_id>}
Stop Session{"command": "stop"}

Global Parameters

  • Event History Pruning (ack_seq): Any command payload can include "ack_seq": <seq> (e.g., {"command": "get-state", "ack_seq": 5}). The daemon will prune all event history up to the acknowledged sequence to optimize memory.

Performance & Blocking

  • Smart Blocking: Commands like pause, stackTrace, and wait-for-event are blocking operations and may take up to 10 seconds depending on the target's execution state.