clawwork-ai / clawwork-ai/ClawWork

[Bug] SkillsSection toggle / install buttons stay spinning when IPC throws

Open Beginner friendly
#399 1 comment 0 reactions 0 assignees View on GitHub
area/ui kind/bug
Dominant language
TypeScript
Stars
532
Forks
75
Avg merge
5h 31m
Merged PRs (30d)
1

Description

## Problem

`SkillsSection.handleToggleEnabled` and `ClawHubTab.handleInstall` both use the pattern:
`setXxx((prev) => new Set(prev).add(key))` → `await window.clawwork.xxx(...)` → `setXxx((prev) => remove key)`.

The cleanup `setXxx` sits after the `await`, outside any `try/finally`. If the IPC call throws, the skill / slug is never removed from the "toggling" / "installing" set and its Power button / Install button stays spinning forever. The user has no way to retry without refreshing the entire section.

## Location

**File:** `packages/desktop/src/renderer/layouts/Settings/sections/SkillsSection.tsx:710-732` (toggle) and `566-583` (install)

```typescript
// handleToggleEnabled
setTogglingKeys((prev) => new Set(prev).add(skill.skillKey));
const newEnabled = skill.disabled;
const res = await window.clawwork.updateSkill(...); // throw → stuck
if (res.ok) { ... } else { ... }
setTogglingKeys((prev) => { const next = new Set(prev); next.delete(skill.skillKey); return next; });

// handleInstall
setInstallingSlugs((prev) => new Set(prev).add(slug));
const res = await window.clawwork.installSkill(gatewayId, { source: 'clawhub', slug }); // throw → stuck
// ... branches ...
setInstallingSlugs((prev) => { const next = new Set(prev); next.delete(slug); return next; });
```

## Fix Approach

Wrap the IPC call in `try/finally` so the set is always cleaned up:

```typescript
setTogglingKeys((prev) => new Set(prev).add(skill.skillKey));
try {
const res = await window.clawwork.updateSkill(...);
if (res.ok) { ... } else { toast.error(...); }
} catch (err) {
console.error('[SkillsSection] toggle failed:', err);
toast.error(t('settings.skillUpdateFailed'));
} finally {
setTogglingKeys((prev) => {
const next = new Set(prev);
next.delete(skill.skillKey);
return next;
});
}
```

Apply the same pattern to `handleInstall`.

## Verification

1. Run `pnpm check` — must pass.
2. Manual: simulate IPC throw during a skill toggle — the button must return to its steady state and a toast should surface the error.

## Context

- **WG:** UI & Design System
- **Priority:** Low (good first issue)
- **Estimated effort:** 15-20 minutes

Contributor guide

Open the contributing guide

Research direction

Open packages/desktop/src/renderer/layouts/Settings/sections/SkillsSection.tsx and inspect handleToggleEnabled around lines 710-732 and handleInstall around lines 566-583. Run pnpm check, then simulate an IPC failure during a toggle or install; done means the button leaves its spinning state and an error toast is shown.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, react, typescript
Domain
desktop, frontend
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.