Skip to content

DAP server: setBreakpoints returns verified=true but JVM never halts (Gradle JDWP attach) #198

@AlexandrosAlexiou

Description

@AlexandrosAlexiou

Hello maintainers, I am experiencing an issue with the breakpoints mechanism in the DAP server.

Disclaimer:

Already aware that DAP is a feature not yet finalised as stated in the latest release, but no harm creating an issue for it.

Issue:

When attaching a DAP client to the kotlin-lsp debug server (started via the
start_debug_server workspace command) against a JVM launched with
--debug-jvm (JDWP suspend=y, address=5005), setBreakpoints is accepted
and returned with verified: true, but the JVM is never actually halted on
those breakpoints. Execution continues past them as if no breakpoint was set.

The attach itself succeeds. The DAP session initializes, the JVM resumes from
its suspend=y pause, and (for long-running programs) the session stays
connected, but no stopped event is ever emitted by the server, and no
breakpoint is ever hit.

Environment

  • kotlin-lsp version: 262.4739.0
  • OS: macOS 15 (arm64)
  • Build tool: Gradle 9.4.1 (stock gradle init Kotlin Application template)
  • JDK: Temurin 21 (project toolchain)

Reproducer

  1. Generate a fresh Kotlin Application project:

    mkdir kotlin-dap-repro && cd kotlin-dap-repro
    gradle init --type kotlin-application --dsl kotlin --package org.example \
                --project-name app --no-split-project --java-version 21
  2. Replace app/src/main/kotlin/org/example/App.kt with a long-running program
    so the JVM doesn't exit before we can observe the lack of stopping:

    package org.example
    
    fun main() {
        while (true) {
            val y = 1 + 1
            Thread.sleep(1000)
        }
    }
  3. Launch with JDWP debugging:

    ./gradlew :app:run --debug-jvm

    Wait for Listening for transport dt_socket at address: 5005.

  4. From a DAP client (any of the below):

    • VSCode: install official kotlin-server-262.4739.0-mac-aarch64.vsix,
      create .vscode/launch.json with
      { "type": "intellij_debugger", "request": "attach", "port": 5005 },
      hit F5.
    • Neovim (nvim-dap): call start_debug_server via
      workspace/executeCommand, then attach with
      { "type": "server", "host": "127.0.0.1", "port": <returned-port> }
      and a launch config of
      { "request": "attach", "port": 5005 }.
  5. Set a breakpoint inside the while (true) loop (e.g., on the
    val y = 1 + 1 line) before attaching.

Expected

The JVM halts on the breakpoint on the first iteration of the loop. A
stopped DAP event is emitted, and the client is able to inspect locals via
scopes/variables.

Actual

  • setBreakpoints returns with verified: true for the line.
  • No breakpoint change event is ever emitted.
  • No stopped event is ever emitted.
  • The loop runs indefinitely, printing nothing, never halting.
  • For short programs (fun main() { println("hi") }) the JVM runs to
    completion immediately after attach and the session ends cleanly, same
    underlying cause: the breakpoint is reported as verified but never fires.

Probably server-side

Reproduced with two independent DAP clients that share nothing but the
kotlin-lsp DAP server:

  1. The official kotlin-server VSCode extension (262.4739.0).
  2. Neovim with nvim-dap and kotlin.nvim.

Both reproduce identically. Neither client sees a stopped event on the wire,
which rules out a client-side rendering or keymap issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions