Skip to content

[Repo Assist] fix(dispatch): remove empty catch swallows; add SafeDispatch/SafeEventInvoke helpers#406

Draft
github-actions[bot] wants to merge 2 commits into
masterfrom
repo-assist/fix-safe-dispatch-empty-catches-365-bd00d86a78f31cc8
Draft

[Repo Assist] fix(dispatch): remove empty catch swallows; add SafeDispatch/SafeEventInvoke helpers#406
github-actions[bot] wants to merge 2 commits into
masterfrom
repo-assist/fix-safe-dispatch-empty-catches-365-bd00d86a78f31cc8

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

🤖 This PR was created by Repo Assist, an automated AI assistant.

Closes #365

Root Cause

Audit of src/ found two recurring AI-slop patterns:

  1. try { DispatcherQueue?.TryEnqueue(...) } catch { }TryEnqueue returns bool and never throws. The try/catch was doing literally nothing, silently hiding any future exception placed inside the lambda.
  2. try { event?.Invoke(...) } catch { } — Silently swallows exceptions thrown by event handlers. Symptoms appear as "activity stream randomly stops updating" with no log entry.

Fix

New helpers (Helpers/SafeDispatch.cs, Helpers/SafeEventInvoke.cs)

// SafeDispatch — extension on DispatcherQueue
public static void SafeEnqueue(this DispatcherQueue? queue, DispatcherQueueHandler action)
    => queue?.TryEnqueue(action);

// SafeEventInvoke — logs instead of swallowing
public static void SafeInvoke<T>(this Action<T>? handler, T arg, IOpenClawLogger? log = null);
public static void SafeInvoke(this Action? handler, IOpenClawLogger? log = null);

HubWindow.xaml.cs

  • Removed 15 useless try { DispatcherQueue?.TryEnqueue(...) } catch { } blocks. The dispatcher call is now direct; the two intentional catches (settings save with comment, and the typed catch (Exception ex)) are untouched.

AudioPipeline.cs

  • Replaced 11 silent try { DiagnosticMessage?.Invoke(...) } catch { } / try { VoiceActivityChanged?.Invoke(...) } catch { } patterns with SafeInvoke(..., _logger). Exceptions from handlers are now logged at Warn rather than discarded.

Trade-offs

  • This is a partial migration (HubWindow + AudioPipeline). The remaining ~80 sites across 39 other files are left for opportunistic follow-up, as the issue proposes.
  • SafeEnqueue is thin — it exists as a named intent marker and to make future callers consistent.

Test Status

Linux CI (this run)

  • dotnet test OpenClaw.Shared.Tests1565 passed, 7 pre-existing failures, 28 skipped
  • dotnet test OpenClaw.Tray.Tests1165 passed (+9 new), 7 pre-existing failures, 47 skipped
  • build.ps1 requires Windows (MakePri.exe); build is infrastructure-limited on Linux — not caused by these changes.

New tests

9 unit tests in SafeEventInvokeTests.cs covering null-safety, single/multi handler invocation, exception containment, and logger integration.

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • az667904.vo.msecnd.net
  • vortex.data.microsoft.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "az667904.vo.msecnd.net"
    - "vortex.data.microsoft.com"

See Network Configuration for more information.

Generated by 🌈 Repo Assist, see workflow run. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@97143ac59cb3a13ef2a77581f929f06719c7402a

github-actions Bot and others added 2 commits May 15, 2026 01:25
…ispatch helpers

Closes #365

- Add SafeDispatch.cs with SafeEnqueue and SafeInvoke<T> extension helpers
- Remove 15 useless try { DispatcherQueue?.TryEnqueue(...) } catch { } blocks
  in HubWindow.xaml.cs — TryEnqueue returns bool, never throws
- Replace 11 silent try { event?.Invoke(...) } catch { } patterns in
  AudioPipeline.cs with SafeInvoke, which logs a Warn when a handler throws
  instead of swallowing the exception silently

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cover SafeEventInvoke<T> and SafeInvoke (no-arg) helpers:
- null handler is a no-op
- single handler is called with correct argument
- multiple handlers all fire in order
- throwing handler does not propagate exception to caller
- throwing handler logs a Warn via IOpenClawLogger
- remaining handlers still fire after a throwing one

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[deep-review][duplication] D2: 106 empty try/catch blocks across 41 files (AI-slop pattern)

0 participants