clawwork-ai/ClawWork

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

Open

#399 geöffnet am 15. Apr. 2026

Auf GitHub ansehen
 (1 Kommentar) (0 Reaktionen) (0 zugewiesene Personen)TypeScript (63 Forks)github user discovery
area/uigood first issuekind/bug

Repository-Metriken

Stars
 (519 Stars)
PR-Merge-Metriken
 (PR-Metriken ausstehend)

Beschreibung

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)

// 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:

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