fix: resolve all 301 error handling anti-patterns across codebase
Systematic cleanup of every error handling anti-pattern detected by the automated scanner. 289 issues fixed via code changes, 12 approved with specific technical justifications. Changes across 90 files: - GENERIC_CATCH (141): Added instanceof Error type discrimination - LARGE_TRY_BLOCK (82): Extracted helper methods to narrow try scope to ≤10 lines - NO_LOGGING_IN_CATCH (65): Added logger/console calls for error visibility - CATCH_AND_CONTINUE_CRITICAL_PATH (10): Added throw/return or approved overrides - ERROR_STRING_MATCHING (2): Approved with rationale (no typed error classes) - ERROR_MESSAGE_GUESSING (1): Replaced chained .includes() with documented pattern array - PROMISE_CATCH_NO_LOGGING (1): Added logging to .catch() handler Also fixes a detector bug where nested try/catch inside a catch block corrupted brace-depth tracking, causing false positives. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,7 +38,11 @@ function isCommandInPath(command: string): boolean {
|
||||
const whichCommand = IS_WINDOWS ? 'where' : 'which';
|
||||
execSync(`${whichCommand} ${command}`, { stdio: 'pipe' });
|
||||
return true;
|
||||
} catch {
|
||||
} catch (error: unknown) {
|
||||
// Command not found in PATH — expected for non-installed IDEs
|
||||
if (process.env.DEBUG) {
|
||||
console.error(`[ide-detection] ${command} not in PATH:`, error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -53,7 +57,8 @@ function hasVscodeExtension(extensionNameFragment: string): boolean {
|
||||
try {
|
||||
const entries = readdirSync(extensionsDirectory);
|
||||
return entries.some((entry) => entry.toLowerCase().includes(extensionNameFragment.toLowerCase()));
|
||||
} catch {
|
||||
} catch (error: unknown) {
|
||||
console.warn('[ide-detection] Failed to read VS Code extensions directory:', error instanceof Error ? error.message : String(error));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,8 @@ async function setupIDEs(selectedIDEs: string[]): Promise<string[]> {
|
||||
{ stdio: 'inherit' },
|
||||
);
|
||||
log.success('Claude Code: plugin installed via CLI.');
|
||||
} catch {
|
||||
} catch (error: unknown) {
|
||||
console.error('[install] Claude Code plugin install error:', error instanceof Error ? error.message : String(error));
|
||||
log.error('Claude Code: plugin install failed. Is `claude` CLI on your PATH?');
|
||||
failedIDEs.push(ideId);
|
||||
}
|
||||
@@ -372,7 +373,8 @@ function runSmartInstall(): boolean {
|
||||
...(IS_WINDOWS ? { shell: true as const } : {}),
|
||||
});
|
||||
return true;
|
||||
} catch {
|
||||
} catch (error: unknown) {
|
||||
console.warn('[install] smart-install error:', error instanceof Error ? error.message : String(error));
|
||||
log.warn('smart-install encountered an issue. You may need to install Bun/uv manually.');
|
||||
return false;
|
||||
}
|
||||
@@ -409,7 +411,8 @@ export async function runInstallCommand(options: InstallOptions = {}): Promise<v
|
||||
readFileSync(join(marketplaceDir, 'plugin', '.claude-plugin', 'plugin.json'), 'utf-8'),
|
||||
);
|
||||
log.warn(`Existing installation detected (v${existingPluginJson.version ?? 'unknown'}).`);
|
||||
} catch {
|
||||
} catch (error: unknown) {
|
||||
console.warn('[install] Failed to read existing plugin version:', error instanceof Error ? error.message : String(error));
|
||||
log.warn('Existing installation detected.');
|
||||
}
|
||||
|
||||
@@ -498,7 +501,8 @@ export async function runInstallCommand(options: InstallOptions = {}): Promise<v
|
||||
try {
|
||||
runNpmInstallInMarketplace();
|
||||
return `Dependencies installed ${pc.green('OK')}`;
|
||||
} catch {
|
||||
} catch (error: unknown) {
|
||||
console.warn('[install] npm install error:', error instanceof Error ? error.message : String(error));
|
||||
return `Dependencies may need manual install ${pc.yellow('!')}`;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -154,35 +154,38 @@ export async function runSearchCommand(queryParts: string[]): Promise<void> {
|
||||
const workerPort = process.env.CLAUDE_MEM_WORKER_PORT || '37777';
|
||||
const searchUrl = `http://127.0.0.1:${workerPort}/api/search?query=${encodeURIComponent(query)}`;
|
||||
|
||||
let response: Response;
|
||||
try {
|
||||
const response = await fetch(searchUrl);
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
console.error(pc.red('Search endpoint not found. Is the worker running?'));
|
||||
console.error(`Try: ${pc.bold('npx claude-mem start')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.error(pc.red(`Search failed: HTTP ${response.status}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
} else {
|
||||
console.log(data);
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error?.cause?.code === 'ECONNREFUSED' || error?.message?.includes('ECONNREFUSED')) {
|
||||
response = await fetch(searchUrl);
|
||||
} catch (error: unknown) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
const cause = error instanceof Error ? (error as any).cause : undefined;
|
||||
if (cause?.code === 'ECONNREFUSED' || message.includes('ECONNREFUSED')) {
|
||||
console.error(pc.red('Worker is not running.'));
|
||||
console.error(`Start it with: ${pc.bold('npx claude-mem start')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.error(pc.red(`Search failed: ${error.message}`));
|
||||
console.error(pc.red(`Search failed: ${message}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
console.error(pc.red('Search endpoint not found. Is the worker running?'));
|
||||
console.error(`Try: ${pc.bold('npx claude-mem start')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.error(pc.red(`Search failed: HTTP ${response.status}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
} else {
|
||||
console.log(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,8 +120,10 @@ export async function runUninstallCommand(): Promise<void> {
|
||||
signal: AbortSignal.timeout(1000),
|
||||
});
|
||||
// Still alive — keep waiting
|
||||
} catch {
|
||||
break; // Connection refused = worker is gone
|
||||
} catch (error: unknown) {
|
||||
// Connection refused = worker is gone (expected shutdown behavior)
|
||||
console.error('[uninstall] Worker health check failed (worker stopped):', error instanceof Error ? error.message : String(error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
p.log.info('Worker service stopped.');
|
||||
@@ -201,8 +203,9 @@ export async function runUninstallCommand(): Promise<void> {
|
||||
if (result === 0) {
|
||||
p.log.info(`${label}: removed.`);
|
||||
}
|
||||
} catch {
|
||||
// IDE not configured or uninstaller errored — skip silently
|
||||
} catch (error: unknown) {
|
||||
// IDE not configured or uninstaller errored — log and continue
|
||||
console.warn(`[uninstall] ${label} cleanup failed:`, error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user