Skip to content

Commit ae50f8e

Browse files
committed
fix(renderer): guard malformed part render in flush
1 parent b656af3 commit ae50f8e

3 files changed

Lines changed: 629 additions & 2 deletions

File tree

lua/opencode/ui/renderer/flush.lua

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,29 @@ local buffer = require('opencode.ui.renderer.buffer')
88
local append = require('opencode.ui.renderer.append')
99

1010
local M = {}
11+
local warned_part_render_error = false
12+
13+
---@param part_id string
14+
---@param message_id string|nil
15+
---@param err any
16+
local function warn_part_render_error_once(part_id, message_id, err)
17+
if warned_part_render_error then
18+
return
19+
end
20+
warned_part_render_error = true
21+
22+
local err_text = tostring(err):gsub('[\r\n]+', ' ')
23+
local msg = string.format(
24+
'Skipped malformed part during render (part=%s message=%s). First error: %s',
25+
tostring(part_id),
26+
tostring(message_id),
27+
err_text
28+
)
29+
30+
vim.schedule(function()
31+
vim.notify_once('[opencode.nvim] ' .. msg, vim.log.levels.WARN)
32+
end)
33+
end
1134

1235
---@generic T
1336
---@param fn fun(): T
@@ -294,11 +317,15 @@ local function format_part(part_id)
294317
end
295318

296319
local is_last_part = (buffer.get_last_part_for_message(message) == part_id)
297-
local formatted = formatter.format_part(rendered_part.part, message, is_last_part, function(session_id)
320+
local ok, formatted_or_err = pcall(formatter.format_part, rendered_part.part, message, is_last_part, function(session_id)
298321
return ctx.render_state:get_child_session_parts(session_id)
299322
end)
323+
if not ok then
324+
warn_part_render_error_once(part_id, rendered_part.message_id, formatted_or_err)
325+
return nil, rendered_part.message_id
326+
end
300327

301-
return formatted, rendered_part.message_id
328+
return formatted_or_err, rendered_part.message_id
302329
end
303330

304331
---@param message_id string

0 commit comments

Comments
 (0)