Skip to content

Commit 044ba01

Browse files
committed
fix(claude): improve error handling and logging in claude runner
Enhance error parsing to provide more user-friendly messages and improve debug logging. Always log basic execution info while keeping detailed logs for debug mode.
1 parent d5dcc92 commit 044ba01

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ Found a bug or have a feature idea? Check our <strong><a href="./CONTRIBUTING.md
197197
## 📖 References
198198

199199
<p align="center">
200-
<table width="100%">
200+
<table align="center">
201201
<tbody>
202202
<tr>
203203
<td align="center">

src/infra/engines/providers/claude/execution/runner.ts

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,15 @@ export async function runClaude(options: RunClaudeOptions): Promise<RunClaudeRes
159159

160160
const { command, args } = buildClaudeExecCommand({ workingDir, prompt, model });
161161

162-
// Debug logging only when LOG_LEVEL=debug
162+
// Debug logging - always log basic info
163+
console.error(`[DEBUG] Claude runner - prompt length: ${prompt.length}, lines: ${prompt.split('\n').length}`);
164+
console.error(`[DEBUG] Claude runner - args: ${args.join(' ')}, model: ${model ?? 'default'}`);
165+
166+
// Additional detailed logging when LOG_LEVEL=debug
163167
if (process.env.LOG_LEVEL === 'debug') {
164-
console.error(`[DEBUG] Claude runner - prompt length: ${prompt.length}, lines: ${prompt.split('\n').length}`);
165-
console.error(`[DEBUG] Claude runner - args count: ${args.length}, model: ${model ?? 'default'}`);
168+
console.error(`[DEBUG] Claude runner - command: ${command} ${args.join(' ')}`);
169+
console.error(`[DEBUG] Claude runner - working dir: ${workingDir}`);
170+
console.error(`[DEBUG] Claude runner - prompt preview: ${prompt.substring(0, 200)}...`);
166171
}
167172

168173
// Create telemetry capture instance
@@ -238,15 +243,50 @@ export async function runClaude(options: RunClaudeOptions): Promise<RunClaudeRes
238243

239244
if (result.exitCode !== 0) {
240245
const errorOutput = result.stderr.trim() || result.stdout.trim() || 'no error output';
241-
const lines = errorOutput.split('\n').slice(0, 10);
242246

243-
console.error('[ERROR] Claude CLI execution failed', {
244-
exitCode: result.exitCode,
245-
error: lines.join('\n'),
246-
command: `${command} ${args.join(' ')}`,
247-
});
247+
// Parse the error to provide a user-friendly message
248+
let errorMessage = `Claude CLI exited with code ${result.exitCode}`;
249+
try {
250+
// Try to parse stream-json output for specific error messages
251+
const lines = errorOutput.split('\n');
252+
for (const line of lines) {
253+
if (line.trim() && line.startsWith('{')) {
254+
const json = JSON.parse(line);
255+
256+
// Check for error in result type
257+
if (json.type === 'result' && json.is_error && json.result) {
258+
errorMessage = json.result;
259+
break;
260+
}
261+
262+
// Check for error in assistant message
263+
if (json.type === 'assistant' && json.error) {
264+
const messageText = json.message?.content?.[0]?.text;
265+
if (messageText) {
266+
errorMessage = messageText;
267+
} else if (json.error === 'rate_limit') {
268+
errorMessage = 'Rate limit reached. Please try again later.';
269+
} else {
270+
errorMessage = json.error;
271+
}
272+
break;
273+
}
274+
}
275+
}
276+
} catch {
277+
// If parsing fails, use the raw error output
278+
const lines = errorOutput.split('\n').slice(0, 10);
279+
if (lines.length > 0 && lines[0]) {
280+
errorMessage = lines.join('\n');
281+
}
282+
}
283+
284+
// Send error to stderr callback if provided
285+
if (onErrorData) {
286+
onErrorData(`\n[ERROR] ${errorMessage}\n`);
287+
}
248288

249-
throw new Error(`Claude CLI exited with code ${result.exitCode}`);
289+
throw new Error(errorMessage);
250290
}
251291

252292
// Log captured telemetry

0 commit comments

Comments
 (0)