Skip to content

fix: validate marks immediately after creation in visual selection - #137

Open
funkybooboo wants to merge 4 commits into
ThePrimeagen:masterfrom
funkybooboo:master
Open

funkybooboo wants to merge 4 commits into
ThePrimeagen:masterfrom
funkybooboo:master

Conversation

@funkybooboo

Copy link
Copy Markdown

Fixes crashes when marks are used before validation during visual selection operations.

Problem

The current code creates marks and immediately uses them for logging and RequestStatus before validating they were created successfully. When the buffer is modified between range calculation and mark creation, the marks fail to create but are still used, causing crashes.

Current flow:

  1. Create marks (may fail silently)
  2. Use marks for logging - crashes if invalid
  3. Pass marks to RequestStatus - crashes if invalid
  4. Start status updates - crashes if invalid
  5. Much later, in async callback, validate marks (too late)

Solution

Validate marks immediately after creation, before using them. This fails fast with a clear error message instead of crashing later with cryptic errors.

New flow:

  1. Create marks
  2. Validate marks immediately
  3. If invalid, log fatal error and return early
  4. If valid, proceed safely knowing marks are good

Benefits

  • Fails fast with clear error message
  • No defensive nil checks needed throughout codebase
  • Single validation point instead of scattered checks
  • Prevents crashes in logging, RequestStatus, and status updates
  • Better user experience with actionable error message

Testing

  • All existing tests pass (68/68)
  • Linting passes
  • Formatting passes
  • Follows existing error handling patterns in the codebase

@cursor

cursor Bot commented Feb 24, 2026

Copy link
Copy Markdown

You have run out of free Bugbot PR reviews for this billing cycle. This will reset on March 8.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Comment thread lua/99/ops/over-range.lua Resolved
Moves mark validation from async on_complete callback to immediately
after mark creation. This prevents crashes when marks are used for
logging or passed to RequestStatus before validation occurs.

Fails fast with clear error message if buffer has been modified and
marks cannot be created, rather than crashing later with cryptic errors.
Copilot AI review requested due to automatic review settings May 28, 2026 02:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds defensive mark creation for visual selections to avoid runtime errors when the buffer/selection changes mid-operation.

Changes:

  • Wrap mark creation in pcall to handle exceptions from mark APIs
  • Validate created marks before storing them in context.marks
  • Log and exit early when marks can’t be created/validated

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

Comment thread lua/99/ops/over-range.lua
Comment on lines +22 to +25
local ok_top, top_mark = pcall(Mark.mark_above_range, range)
local ok_bottom, bottom_mark = pcall(Mark.mark_point, range.buffer, range.end_)

if not ok_top or not ok_bottom or not top_mark:is_valid() or not bottom_mark:is_valid() then
Comment thread lua/99/ops/over-range.lua

if not ok_top or not ok_bottom or not top_mark:is_valid() or not bottom_mark:is_valid() then
logger:fatal(
"Cannot create marks for visual selection. Buffer may have been modified."
Comment thread lua/99/ops/over-range.lua
Comment on lines +22 to +29
local ok_top, top_mark = pcall(Mark.mark_above_range, range)
local ok_bottom, bottom_mark = pcall(Mark.mark_point, range.buffer, range.end_)

if not ok_top or not ok_bottom or not top_mark:is_valid() or not bottom_mark:is_valid() then
logger:fatal(
"Cannot create marks for visual selection. Buffer may have been modified."
)
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: If one of two extmark creation calls fails, the successfully created mark is not cleaned up, leading to a resource leak.
Severity: MEDIUM

Suggested Fix

Before returning early on a partial failure, check if top_mark or bottom_mark were successfully created and, if so, call their respective delete() methods to ensure no extmarks are leaked.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: lua/99/ops/over-range.lua#L22-L29

Potential issue: In `over-range.lua`, two extmarks, `top_mark` and `bottom_mark`, are
created in separate `pcall` blocks. If one of these calls succeeds but the other fails,
a subsequent validation check will trigger an early return. However, the successfully
created extmark is not cleaned up during this early return because it is only added to
the tracked `context.marks` list after the validation has already passed. This results
in an orphaned extmark that persists in the buffer, causing a resource leak that can
accumulate over time and may lead to performance degradation.

Did we get this right? 👍 / 👎 to inform future reviews.

Comment thread lua/99/providers.lua
Comment on lines +317 to +327
return {
"pi",
"--print",
"--provider",
"opencode-go",
"--model",
context.model or "qwen3.7-plus",
"--no-context-files",
query,
}
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: The new PiProvider._build_command function constructs a command for pi but doesn't specify where to write the output, leading to empty responses and silent failures.
Severity: MEDIUM

Suggested Fix

Modify PiProvider._build_command to correctly instruct the pi command where to write its output. This likely involves adding an argument to the command string that points to context.tmp_file, similar to how other providers are implemented. This will ensure that _retrieve_response can successfully read the AI's output.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: lua/99/providers.lua#L316-L327

Potential issue: The newly introduced `PiProvider` has an incomplete implementation in
its `_build_command` method. This function assembles the command to be executed but
fails to include an argument specifying the output file path. Consequently, when
`BaseProvider:make_request` calls `_retrieve_response`, it attempts to read from
`context.tmp_file`, which remains empty because the `pi` command never wrote its output
to it. This results in silent failures, such as a "response was empty" message, for any
operation that relies on the AI's response being written to a temporary file, like
visual selection or search.

Did we get this right? 👍 / 👎 to inform future reviews.

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.

2 participants