Fix session completion not rendering + diagnostic lifecycle logging#145
Merged
Fix session completion not rendering + diagnostic lifecycle logging#145
Conversation
Log critical lifecycle events to ~/.polypilot/event-diagnostics.log: - [EVT] SessionIdleEvent/TurnEnd/Error with IsProcessing state and thread ID - [EVT-WARN] Events delivered to orphaned (replaced) state objects - [EVT-ERR] Exceptions in SyncContext.Post callbacks and CompleteReasoningMessages - [IDLE] CompleteResponse dispatch confirmation on UI thread - [COMPLETE] CompleteResponse entry/skip with IsProcessing guard result - [SEND] IsProcessing=true set point with thread ID - [RECONNECT] Old/new state swap with session IDs - [UI-ERR] InvokeOnUI callback failures Also wraps SyncContext.Post callbacks in try-catch to prevent silent exception swallowing — the most likely root cause of stuck sessions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…es, symmetric try-catch Fixes from GPT-5.3, Sonnet 4.6, Opus 4.6, Gemini, GPT-5 code reviews: - Add try-catch to 'else' branches of Invoke() and InvokeOnUI() (asymmetric bug) - Use ex.ToString() instead of ex.Message for full stack traces in diagnostics - Add lock(_diagnosticLogLock) around File.AppendAllText for thread safety - Add 10MB log rotation to prevent unbounded event-diagnostics.log growth - Wrap CompleteReasoningMessages in try-catch for AssistantTurnEndEvent (was only protected in SessionIdleEvent) - Fix 'UI thread' misnomer in IDLE log message - Add comment explaining why orphaned handlers are not early-returned Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move FileInfo size check inside the lock to prevent race where multiple threads check size, all pass, and delete concurrently. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When CompleteResponse fires OnStateChanged followed by OnSessionComplete, the RefreshState handler may be throttled (500ms window) causing the sessions list to not be refreshed. HandleComplete then calls ScheduleRender but renders stale data — the session still appears as 'Thinking'. Fix: refresh sessions list in HandleComplete so the scheduled render always has up-to-date IsProcessing state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Sessions appear stuck showing "Thinking" even after the Copilot SDK has delivered
SessionIdleEventandCompleteResponsehas run successfully. Users must click Stop to see the buffered response.Root Cause
UI render throttle race condition in Dashboard.razor:
CompleteResponsefiresOnStateChangedthenOnSessionCompletesequentiallyAssistantTurnEndEvents consume the 500ms throttle windowOnStateChangedfires, the throttle drops it →sessionslist not refreshedHandleComplete→ScheduleRender()fires, but renders stale dataDiagnosed via new diagnostic logging — the
event-diagnostics.logshowed:Fix
Throttle race fix (Dashboard.razor): Refresh
sessionslist inHandleCompletebeforeScheduleRender()so the render always has currentIsProcessingstate.SyncContext.Post try-catch (CopilotService.Events.cs, CopilotService.cs): Wrap all
SyncContext.Postcallbacks in try-catch. On MAUI, exceptions in Post callbacks silently disappear — this prevented a class of bugs where event processing could fail without any trace.Diagnostic lifecycle logging (
#if DEBUGonly):[SEND]→[EVT]→[IDLE]→[COMPLETE]tracing with timestamps and thread IDs, written to~/.polypilot/event-diagnostics.log. Thread-safe via lock, 10MB rotation. This caught the root cause within 1 hour of deployment.Orphaned handler detection: Warns when old event handlers (from pre-reconnect state) deliver events, with comment explaining why they're not early-returned (shared Info object).
Testing
AssistantTurnEndEventflowRelated