Skip to content

fix: prevent skill catalog infinite loop on persistent fetch errors#2012

Merged
jolestar merged 1 commit into
mainfrom
fix/skill-catalog-error-loop
Jun 25, 2026
Merged

fix: prevent skill catalog infinite loop on persistent fetch errors#2012
jolestar merged 1 commit into
mainfrom
fix/skill-catalog-error-loop

Conversation

@jolestar

Copy link
Copy Markdown
Collaborator

Summary

Follow-up fix for a regression introduced in #1999 (web-gui-followup-3).

Problem: The skills page effect guard was changed from catalog.length > 0 to source !== "fixture" to fix an infinite reload loop when the catalog is legitimately empty. However, the catch block in refreshSkillCatalog (runtime-store.ts:918) preserves the old source value:

// catch:
skillCatalog: { ...state.skillCatalog, error: message },

Since emptySkillCatalog.source is "fixture" and the error path does not change it, source stays "fixture" while skillCatalogLoading returns to false. The effect guard passes again, re-firing refreshSkillCatalog in a tight loop — the same freeze #1999 intended to fix, just shifted from empty-success to persistent-error.

Fix: Set source: "http" in the catch block so the guard recognizes a load attempt was made:

skillCatalog: { ...state.skillCatalog, source: "http", error: message },

This mirrors the existing pattern in refreshSkillDetail (line 942), which already sets source: "http" on error.

Verification

  • npm run build (typecheck + vite build) passes ✓

Identified by holonbot review on #1999.

@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
holon Ready Ready Preview, Comment Jun 25, 2026 6:25pm

@holonbot holonbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve. The one-line fix is correct and minimal: setting source: "http" in the refreshSkillCatalog catch block breaks the effect-guard re-fire loop on persistent fetch errors, mirroring the existing refreshSkillDetail error path. The other catch blocks in this file (addSkill/removeSkill/updateSkill/checkSkill) share the old pattern but are user-initiated (button handlers), not effect-driven, so they cannot loop — no change needed in this PR.

const message = error instanceof Error ? error.message : String(error);
set((state) => ({
skillCatalog: { ...state.skillCatalog, error: message },
skillCatalog: { ...state.skillCatalog, source: "http", error: message },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (no action needed for this PR): Four other catch blocks below (addSkillToCatalog, removeSkillFromCatalog, updateSkillCatalog, checkSkillCatalog) still use { ...state.skillCatalog, error: message } without source: "http". They are safe today because they are invoked from button handlers, not the effect guard, so they cannot loop. A future consistency pass could align all skillCatalog error paths.

@holonbot

holonbot Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Holon Run Report

@jolestar
jolestar merged commit d4841ef into main Jun 25, 2026
3 checks passed
@jolestar
jolestar deleted the fix/skill-catalog-error-loop branch June 25, 2026 18:33
@jolestar
jolestar restored the fix/skill-catalog-error-loop branch June 26, 2026 00:57
@jolestar
jolestar deleted the fix/skill-catalog-error-loop branch June 26, 2026 00:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant