What it does
Flags `catch` clauses that use `catch (e: any)` or `catch (e: unknown)` without then narrowing the type before using the error. Also flags patterns where the error is typed so broadly that all type information is lost.
Why AI tools generate this pattern
When AI generates try/catch blocks, it defaults to the broadest possible catch signature. This hides important information: *what kind of error occurred?* A database connection error needs different handling than a validation error, which needs different handling than a downstream API timeout. Broad exception catching also makes it impossible for TypeScript to help you — you lose all type safety on the `e` variable, leading to more `e: any` casts and less reliable error handling down the chain.
Code Examples
try {
await db.users.create(data);
} catch (e: any) { // ← all type info lost
console.error(e.message); // might not have .message
res.status(500).json({ error: e }); // might leak internal details
}try {
await db.users.create(data);
} catch (err) {
// Narrow the type before using it
if (err instanceof DatabaseConstraintError) {
res.status(409).json({ error: 'User already exists' });
return;
}
if (err instanceof Error) {
console.error('Database error:', err.message);
res.status(500).json({ error: 'Internal server error' });
return;
}
throw err; // re-throw unexpected error types
}How to Fix
- Use type narrowing inside the catch block:
- Check `instanceof Error` or more specific error types
- Use a type guard utility (`isAxiosError(err)`, `isPrismaError(err)`, etc.)
- If you truly need to handle unknown errors, use `catch (err: unknown)` and narrow before use
Nuances & False Positive Prevention
Legitimate usage can be exempted with inline disable comments (// ai-guard-disable-next-line no-broad-exception) when appropriate.
Configuration
Enable or override this rule in your ESLint configuration:
// eslint.config.mjs
export default [
{
plugins: { 'ai-guard': aiGuard },
rules: {
'ai-guard/no-broad-exception': 'warn',
},
},
];