Skip to content

Bug: force_complete_request does not handle Running state — potential coordinator deadlock #396

@karthiknadig

Description

@karthiknadig

Summary

RefreshCoordinator::force_complete_request() only handles the Completing and Idle states. If begin_completion() panics with an "unexpected key" error, the coordinator state is restored to Running before the panic. The RefreshCompletionGuard::drop then calls force_complete_request(), which hits the _ => {} wildcard arm — leaving the coordinator permanently stuck in Running.

Root Cause

In crates/pet/src/jsonrpc.rs:

  1. Line 148-150 (begin_completion): On key mismatch, state is restored to Running(active) before panicking
  2. Line 273-278 (RefreshCompletionGuard::drop): Calls force_complete_request() during stack unwind
  3. Line 210-220 (force_complete_request): Only transitions Completing → Idle. The Running state matches _ => {} — a silent no-op.

Impact

After the panic, the coordinator is stuck in Running with no thread owning the refresh. All future refresh requests call wait_until_idle() and hang forever — deadlocking the JSONRPC server.

While the "unexpected key" panic is a defensive assertion that shouldn't fire in normal operation, if it ever fires (e.g., due to a future code change or race condition), the server becomes completely unresponsive.

Proposed Fix

Either:

  1. Have force_complete_request() also handle the Running state by transitioning to Idle + notify_all(), OR
  2. Return a Result from begin_completion() instead of panicking, allowing proper error recovery

Introduced By

PR #386 (d3a060f — fix: deduplicate concurrent refresh requests)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIssue identified by VS Code Team member as probable bug

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions