From 712af16138fbb07e441b309782128132597f3328 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Thu, 9 Apr 2026 04:45:15 -1000 Subject: [PATCH] refactor: replace empty catches with selective error handling in sidebar-agent Convert 8 empty catch blocks to selective catches that check err.code (ESRCH for process kills, ENOENT for file ops). Import safeUnlink for cancel file cleanup. Unexpected errors now propagate instead of being silently swallowed. Co-Authored-By: Claude Opus 4.6 (1M context) --- browse/src/sidebar-agent.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/browse/src/sidebar-agent.ts b/browse/src/sidebar-agent.ts index 43b04b06..215c717b 100644 --- a/browse/src/sidebar-agent.ts +++ b/browse/src/sidebar-agent.ts @@ -12,6 +12,7 @@ import { spawn } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; +import { safeUnlink } from './error-handling'; const QUEUE = process.env.SIDEBAR_QUEUE_PATH || path.join(process.env.HOME || '/tmp', '.gstack', 'sidebar-agent-queue.jsonl'); const KILL_FILE = path.join(path.dirname(QUEUE), 'sidebar-agent-kill'); @@ -290,7 +291,7 @@ async function askClaude(queueEntry: QueueEntry): Promise { // Clear any stale cancel signal for this tab before starting const cancelFile = cancelFileForTab(tid); - try { fs.unlinkSync(cancelFile); } catch {} + safeUnlink(cancelFile); const proc = spawn('claude', claudeArgs, { stdio: ['pipe', 'pipe', 'pipe'], @@ -321,12 +322,12 @@ async function askClaude(queueEntry: QueueEntry): Promise { try { if (fs.existsSync(cancelFile)) { console.log(`[sidebar-agent] Cancel signal received for tab ${tid} — killing claude subprocess`); - try { proc.kill('SIGTERM'); } catch {} - setTimeout(() => { try { proc.kill('SIGKILL'); } catch {} }, 3000); + try { proc.kill('SIGTERM'); } catch (err: any) { if (err?.code !== 'ESRCH') throw err; } + setTimeout(() => { try { proc.kill('SIGKILL'); } catch (err: any) { if (err?.code !== 'ESRCH') throw err; } }, 3000); fs.unlinkSync(cancelFile); clearInterval(cancelCheck); } - } catch {} + } catch (err: any) { if (err?.code !== 'ENOENT') throw err; } }, 500); let buffer = ''; @@ -385,7 +386,7 @@ async function askClaude(queueEntry: QueueEntry): Promise { try { proc.kill('SIGTERM'); } catch (killErr: any) { console.warn(`[sidebar-agent] Tab ${tid}: Failed to kill timed-out process:`, killErr.message); } - setTimeout(() => { try { proc.kill('SIGKILL'); } catch {} }, 3000); + setTimeout(() => { try { proc.kill('SIGKILL'); } catch (err: any) { if (err?.code !== 'ESRCH') throw err; } }, 3000); const timeoutMsg = stderrBuffer.trim() ? `Timed out after ${timeoutMs / 1000}s\nstderr: ${stderrBuffer.trim().slice(-500)}` : `Timed out after ${timeoutMs / 1000}s`; @@ -464,8 +465,8 @@ function pollKillFile(): void { if (activeProcs.size > 0) { console.log(`[sidebar-agent] Kill signal received — terminating ${activeProcs.size} active agent(s)`); for (const [tid, proc] of activeProcs) { - try { proc.kill('SIGTERM'); } catch {} - setTimeout(() => { try { proc.kill('SIGKILL'); } catch {} }, 2000); + try { proc.kill('SIGTERM'); } catch (err: any) { if (err?.code !== 'ESRCH') throw err; } + setTimeout(() => { try { proc.kill('SIGKILL'); } catch (err: any) { if (err?.code !== 'ESRCH') throw err; } }, 2000); processingTabs.delete(tid); } activeProcs.clear(); @@ -480,7 +481,7 @@ async function main() { const dir = path.dirname(QUEUE); fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); if (!fs.existsSync(QUEUE)) fs.writeFileSync(QUEUE, '', { mode: 0o600 }); - try { fs.chmodSync(QUEUE, 0o600); } catch {} + try { fs.chmodSync(QUEUE, 0o600); } catch (err: any) { if (err?.code !== 'ENOENT') throw err; } lastLine = countLines(); await refreshToken();