From 41471fa83025f65763e8153282669c871a348e71 Mon Sep 17 00:00:00 2001 From: Jacob Segal Date: Sun, 25 Jan 2026 00:38:33 -0800 Subject: [PATCH] fix(core): only fail startup on actual errors The latest version of OpenCode (1.1.35) outputs a log line to stderr on startup (see https://github.com/anomalyco/opencode/issues/10506 ). This causes the NeoVim plugin to hang indefinitely. This commit makes two changes: 1. If we fail to start the OpenCode server, we display a notification with the error rather than hanging indefinitely. 2. We don't allow DEBUG, INFO, or WARN-level messages to fail initialization. --- lua/opencode/core.lua | 12 +++++++++++- lua/opencode/opencode_server.lua | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lua/opencode/core.lua b/lua/opencode/core.lua index b36546e3..a0457cdf 100644 --- a/lua/opencode/core.lua +++ b/lua/opencode/core.lua @@ -85,7 +85,17 @@ M.open = Promise.async(function(opts) ui.focus_output({ restore_position = are_windows_closed }) end - local server = server_job.ensure_server():await() + local server + local server_ok, server_err = pcall(function() + server = server_job.ensure_server():await() + end) + + if not server_ok or not server then + state.is_opening = false + vim.notify('Failed to start opencode server: ' .. tostring(server_err or 'Unknown error'), vim.log.levels.ERROR) + return Promise.new():reject(server_err or 'Server failed to start') + end + state.opencode_server = server local ok, err = pcall(function() diff --git a/lua/opencode/opencode_server.lua b/lua/opencode/opencode_server.lua index 23bb534f..293255d1 100644 --- a/lua/opencode/opencode_server.lua +++ b/lua/opencode/opencode_server.lua @@ -100,9 +100,21 @@ function OpencodeServer:spawn(opts) end end, stderr = function(err, data) - if err or data then - self.spawn_promise:reject(err or data) - safe_call(opts.on_error, err or data) + if err then + self.spawn_promise:reject(err) + safe_call(opts.on_error, err) + return + end + if data then + -- Filter out INFO/WARN/DEBUG log lines (not actual errors) + local log_level = data:match('^%s*(%u+)%s') + if log_level and (log_level == 'INFO' or log_level == 'WARN' or log_level == 'DEBUG') then + -- Ignore log lines, don't reject + return + end + -- Only reject on actual errors + self.spawn_promise:reject(data) + safe_call(opts.on_error, data) end end, }, function(exit_opts)