Skip to content

Commit 5cad4be

Browse files
committed
fix: add missing error handling and bounds checking
- Add .catch() handlers for unhandled promise rejections in CLI - Add bounds checking before array access in chat.tsx - Add error logging to silent catch blocks in SDK - Add proper error reporting in agents/commander.ts - Improve error messages in agents/thinker/thinker.ts
1 parent 7037441 commit 5cad4be

File tree

8 files changed

+41
-16
lines changed

8 files changed

+41
-16
lines changed

agents/commander.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ Do not use any tools! Only analyze the output of the command.`,
6363
handleSteps: function* ({ params }: AgentStepContext) {
6464
const command = params?.command as string | undefined
6565
if (!command) {
66+
// Using console.error because agents run in a sandboxed environment without access to structured logger
67+
console.error('Commander agent: missing required "command" parameter')
68+
yield {
69+
toolName: 'set_output',
70+
input: { output: 'Error: Missing required "command" parameter' },
71+
}
6672
return
6773
}
6874

@@ -81,7 +87,8 @@ Do not use any tools! Only analyze the output of the command.`,
8187
if (rawOutput) {
8288
// Return the raw command output without summarization
8389
const result = toolResult?.[0]
84-
const output = result?.type === 'json' ? result.value : ''
90+
// Only return object values (command output objects), not plain strings
91+
const output = result?.type === 'json' && typeof result.value === 'object' ? result.value : ''
8592
yield {
8693
toolName: 'set_output',
8794
input: { output },

agents/thinker/thinker.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,12 @@ When satisfied, write out a brief response to the user's request. The parent age
4646
.find((m) => m.role === 'assistant')
4747

4848
if (!lastAssistantMessage) {
49+
const errorMsg = 'Error: No assistant message found in conversation history'
50+
// Using console.error because agents run in a sandboxed environment without access to structured logger
51+
console.error('Thinker agent:', errorMsg)
4952
yield {
5053
toolName: 'set_output',
51-
input: { message: 'No response generated' },
54+
input: { message: errorMsg },
5255
}
5356
return
5457
}

cli/src/chat.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ export const Chat = ({
543543
{ error },
544544
'[followup-click] onSubmitPrompt failed with error',
545545
)
546+
showClipboardMessage('Failed to send followup', { durationMs: 3000 })
546547
})
547548
}
548549

@@ -997,12 +998,12 @@ export const Chat = ({
997998
let replacement: string
998999
const index = agentSelectedIndex
9991000
if (index < agentMatches.length) {
1000-
const selected = agentMatches[index] || agentMatches[0]
1001+
const selected = agentMatches.length > 0 ? (agentMatches[index] || agentMatches[0]) : undefined
10011002
if (!selected) return
10021003
replacement = `@${selected.displayName} `
10031004
} else {
10041005
const fileIndex = index - agentMatches.length
1005-
const selectedFile = fileMatches[fileIndex] || fileMatches[0]
1006+
const selectedFile = fileMatches.length > 0 ? (fileMatches[fileIndex] || fileMatches[0]) : undefined
10061007
if (!selectedFile) return
10071008
replacement = `@${selectedFile.filePath} `
10081009
}
@@ -1060,12 +1061,20 @@ export const Chat = ({
10601061
}
10611062

10621063
const cwd = getProjectRoot() ?? process.cwd()
1063-
void addPendingImageFromFile(result.imagePath, cwd, placeholderPath)
1064+
addPendingImageFromFile(result.imagePath, cwd, placeholderPath).catch(
1065+
(error) => {
1066+
logger.error({ error }, 'Failed to add pending image from file')
1067+
showClipboardMessage('Failed to add image', { durationMs: 3000 })
1068+
}
1069+
)
10641070
}, 0)
10651071
},
10661072
onPasteImagePath: (imagePath: string) => {
10671073
const cwd = getProjectRoot() ?? process.cwd()
1068-
void validateAndAddImage(imagePath, cwd)
1074+
validateAndAddImage(imagePath, cwd).catch((error) => {
1075+
logger.error({ error, imagePath }, 'Failed to validate and add image')
1076+
showClipboardMessage('Failed to add image', { durationMs: 3000 })
1077+
})
10691078
},
10701079
onPasteText: (text: string) => {
10711080
setInputValue((prev) => {

cli/src/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,4 +343,7 @@ async function main(): Promise<void> {
343343
)
344344
}
345345

346-
void main()
346+
main().catch((error) => {
347+
logger.error(error, 'Unhandled error in main')
348+
process.exit(1)
349+
})

cli/src/init/init-app.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ export async function initializeApp(params: { cwd?: string }): Promise<void> {
2626
// This ensures the subscription status is up-to-date on startup
2727
const claudeCredentials = getClaudeOAuthCredentials()
2828
if (claudeCredentials) {
29-
void getValidClaudeOAuthCredentials().catch(() => {
30-
// Silently ignore refresh errors - will be retried on next API call
29+
getValidClaudeOAuthCredentials().catch((error) => {
30+
// Log refresh errors at debug level - will be retried on next API call
31+
console.debug('Failed to refresh Claude OAuth credentials:', error)
3132
})
3233
}
3334
}

cli/src/utils/analytics.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,18 @@ function logAnalyticsDebug(message: string, data: Record<string, unknown>) {
8888
if (!DEBUG_ANALYTICS) {
8989
return
9090
}
91-
void loadLogger()
91+
loadLogger()
9292
.then(({ logger }) => {
9393
logger.debug(data, message)
9494
})
95-
.catch(() => {
95+
.catch((error) => {
9696
try {
9797
console.debug(message, data)
9898
} catch {
9999
// Ignore console errors in restricted environments
100100
}
101+
// Log the error to help diagnose logger issues in debug mode
102+
console.debug('Failed to load logger for analytics:', error)
101103
})
102104
}
103105

sdk/src/agents/load-agents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ const getAllAgentFiles = (dir: string): string[] => {
126126
}
127127
}
128128
} catch {
129-
// Ignore missing agent directories
129+
// Expected for user agent directories that may not exist
130130
}
131131
return files
132132
}

sdk/src/run-state.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,8 @@ export async function loadUserKnowledgeFiles(params: {
318318
let entries: string[]
319319
try {
320320
entries = await fs.readdir(homeDir)
321-
} catch {
322-
logger.debug?.({ homeDir }, 'Failed to read home directory')
321+
} catch (error) {
322+
logger.debug?.({ homeDir, error: getErrorObject(error) }, 'Failed to read home directory')
323323
return userKnowledgeFiles
324324
}
325325

@@ -347,8 +347,8 @@ export async function loadUserKnowledgeFiles(params: {
347347
userKnowledgeFiles[tildeKey] = content
348348
// Only use the first file found (highest priority)
349349
break
350-
} catch {
351-
logger.debug?.({ filePath }, 'Failed to read user knowledge file')
350+
} catch (error) {
351+
logger.debug?.({ filePath, error: getErrorObject(error) }, 'Failed to read user knowledge file')
352352
}
353353
}
354354
}

0 commit comments

Comments
 (0)