clawwork-ai / clawwork-ai/ClawWork
[Bug] SkillsSection toggle / install buttons stay spinning when IPC throws
- 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
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