Skip to content

fix(server): preserve self binding in heartbeat timer disconnect#305

Merged
nickjvandyke merged 1 commit into
nickjvandyke:mainfrom
yyueniao:fix/heartbeat-timer-self-dispatch
Jun 26, 2026
Merged

fix(server): preserve self binding in heartbeat timer disconnect#305
nickjvandyke merged 1 commit into
nickjvandyke:mainfrom
yyueniao:fix/heartbeat-timer-self-dispatch

Conversation

@yyueniao

Copy link
Copy Markdown
Contributor

Tasks

  • I read CONTRIBUTING.md
  • I ensured my changes pass automated checks
  • I reviewed and understand the AI-generated code in my changes (if any)

Description

Fixed a bug in Server:connect() where the heartbeat timer callback self.disconnect was passed as a bare function reference, losing the implicit self receiver. When the timer fired, it would attempt to call disconnect() without the correct self context, causing a runtime error.

How to reproduce

  1. Open nvim with opencode configured and start a session
  2. Mock a server hang by suspending the server process: pkill -STOP opencode
  3. Observe the error message — the heartbeat timer callback fails because self is nil
  4. Resume the server afterward: pkill -CONT opencode

The fix wraps the callback in a closure to preserve the self binding:

-- Before
vim.schedule_wrap(self.disconnect)

-- After
vim.schedule_wrap(function()
  self:disconnect()
end)

Testing

  1. Verify that :checkhealth opencode passes
  2. Connect to an opencode server and confirm the heartbeat timer fires without errors
  3. Disconnect and reconnect to ensure no regressions in the connect/disconnect flow

Related Issue(s)

Screenshots/Videos

N/A

Copilot AI review requested due to automatic review settings June 26, 2026 00:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a Neovim/Lua method-binding bug in Server:connect() where the heartbeat timer callback previously passed self.disconnect as a bare function reference, causing the method to be invoked without the correct self receiver when the timer fired.

Changes:

  • Wrap the heartbeat timer disconnect callback in a closure so it calls self:disconnect() with the correct receiver.
  • Reformat the uv_timer:start(...) call for readability while applying the fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@nickjvandyke

Copy link
Copy Markdown
Owner

Ope thank you! I noticed this error occasionally but presumed it'd be complicated and didn't have time to investigate.

@nickjvandyke nickjvandyke merged commit 43adb10 into nickjvandyke:main Jun 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants