fix: improve error handling by returning specific error messages in skill routes and IPC handlers (#945)

This commit is contained in:
Felix
2026-04-30 18:33:03 +08:00
committed by GitHub
parent d18985712c
commit e545fa2194
4 changed files with 22 additions and 19 deletions

View File

@@ -28,7 +28,7 @@ export async function handleSkillRoutes(
env: body.env,
}));
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -58,7 +58,7 @@ export async function handleSkillRoutes(
skills: filterEnabledQuickAccessSkills(scannedSkills, runtimeSkills, configs),
});
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -70,7 +70,7 @@ export async function handleSkillRoutes(
capability: await ctx.clawHubService.getMarketplaceCapability(),
});
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -83,7 +83,7 @@ export async function handleSkillRoutes(
results: await ctx.clawHubService.search(body),
});
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -94,7 +94,7 @@ export async function handleSkillRoutes(
await ctx.clawHubService.install(body);
sendJson(res, 200, { success: true });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -105,7 +105,7 @@ export async function handleSkillRoutes(
await ctx.clawHubService.uninstall(body);
sendJson(res, 200, { success: true });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -114,7 +114,7 @@ export async function handleSkillRoutes(
try {
sendJson(res, 200, { success: true, results: await ctx.clawHubService.listInstalled() });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -125,7 +125,7 @@ export async function handleSkillRoutes(
await ctx.clawHubService.openSkillReadme(body.skillKey || body.slug || '', body.slug, body.baseDir);
sendJson(res, 200, { success: true });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}
@@ -136,7 +136,7 @@ export async function handleSkillRoutes(
await ctx.clawHubService.openSkillPath(body.skillKey || body.slug || '', body.slug, body.baseDir);
sendJson(res, 200, { success: true });
} catch (error) {
sendJson(res, 500, { success: false, error: String(error) });
sendJson(res, 500, { success: false, error: error instanceof Error ? error.message : String(error) });
}
return true;
}

View File

@@ -2085,7 +2085,7 @@ function registerClawHubHandlers(clawHubService: ClawHubService): void {
const results = await clawHubService.search(params);
return { success: true, results };
} catch (error) {
return { success: false, error: String(error) };
return { success: false, error: error instanceof Error ? error.message : String(error) };
}
});
@@ -2095,7 +2095,7 @@ function registerClawHubHandlers(clawHubService: ClawHubService): void {
await clawHubService.install(params);
return { success: true };
} catch (error) {
return { success: false, error: String(error) };
return { success: false, error: error instanceof Error ? error.message : String(error) };
}
});
@@ -2105,7 +2105,7 @@ function registerClawHubHandlers(clawHubService: ClawHubService): void {
await clawHubService.uninstall(params);
return { success: true };
} catch (error) {
return { success: false, error: String(error) };
return { success: false, error: error instanceof Error ? error.message : String(error) };
}
});
@@ -2115,7 +2115,7 @@ function registerClawHubHandlers(clawHubService: ClawHubService): void {
const results = await clawHubService.listInstalled();
return { success: true, results };
} catch (error) {
return { success: false, error: String(error) };
return { success: false, error: error instanceof Error ? error.message : String(error) };
}
});

View File

@@ -685,7 +685,7 @@ export function Skills() {
<span>
{SEARCH_ERROR_CODES.has(searchError.replace('Error: ', ''))
? t(`toast.${searchError.replace('Error: ', '')}`, { path: skillsDirPath })
: t('marketplace.searchError')}
: searchError}
</span>
</div>
)}

View File

@@ -39,7 +39,7 @@ type ClawHubListResult = {
function mapErrorCodeToSkillErrorKey(
code: AppError['code'],
operation: 'fetch' | 'search' | 'install',
): string {
): string | null {
if (code === 'TIMEOUT') {
return operation === 'search'
? 'searchTimeoutError'
@@ -54,7 +54,7 @@ function mapErrorCodeToSkillErrorKey(
? 'installRateLimitError'
: 'fetchRateLimitError';
}
return 'rateLimitError';
return null;
}
interface SkillsState {
@@ -172,8 +172,9 @@ export const useSkillsStore = create<SkillsState>((set, get) => ({
} catch (error) {
console.error('Failed to fetch skills:', error);
const appError = normalizeAppError(error, { module: 'skills', operation: 'fetch' });
const errorKey = mapErrorCodeToSkillErrorKey(appError.code, 'fetch');
// Preserve previous skills on error (stale-while-revalidate).
set((prev) => ({ loading: false, error: mapErrorCodeToSkillErrorKey(appError.code, 'fetch'), skills: prev.skills }));
set((prev) => ({ loading: false, error: errorKey ?? appError.message, skills: prev.skills }));
}
},
@@ -194,7 +195,8 @@ export const useSkillsStore = create<SkillsState>((set, get) => ({
}
} catch (error) {
const appError = normalizeAppError(error, { module: 'skills', operation: 'search' });
set({ searchError: mapErrorCodeToSkillErrorKey(appError.code, 'search') });
const errorKey = mapErrorCodeToSkillErrorKey(appError.code, 'search');
set({ searchError: errorKey ?? appError.message });
} finally {
set({ searching: false });
}
@@ -212,7 +214,8 @@ export const useSkillsStore = create<SkillsState>((set, get) => ({
module: 'skills',
operation: 'install',
});
throw new Error(mapErrorCodeToSkillErrorKey(appError.code, 'install'));
const errorKey = mapErrorCodeToSkillErrorKey(appError.code, 'install');
throw new Error(errorKey ?? appError.message);
}
// Refresh skills after install
await get().fetchSkills();