fix: improve error handling by returning specific error messages in skill routes and IPC handlers (#945)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) };
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user