fix(worker): include stdout in error messages when Claude command fails
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Auth errors like "OAuth token has expired" were lost because Claude writes them to stdout, not stderr. The error message only showed kubectl's generic "command terminated with exit code 1". Now includes both stdout and stderr in the error, making failures immediately diagnosable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b7d0e84946
commit
cefc15aa7d
@ -162,6 +162,8 @@ func (a *Adapter) Execute(ctx context.Context, req *domain.AgentRequest, handler
|
||||
}
|
||||
|
||||
// Determine exit code and error
|
||||
stdoutStr := finalOutput.String()
|
||||
stderrStr := stderrOutput.String()
|
||||
if cmdErr != nil {
|
||||
if exitErr, ok := cmdErr.(*exec.ExitError); ok {
|
||||
result.ExitCode = exitErr.ExitCode()
|
||||
@ -169,17 +171,17 @@ func (a *Adapter) Execute(ctx context.Context, req *domain.AgentRequest, handler
|
||||
result.ExitCode = 1
|
||||
result.Error = cmdErr
|
||||
}
|
||||
// Include stderr and troubleshooting help in error
|
||||
result.Error = a.buildErrorWithHelp(result.Error, stderrOutput.String(), namespace, podName)
|
||||
// Include stdout, stderr, and troubleshooting help in error
|
||||
result.Error = a.buildErrorWithHelp(result.Error, stderrStr, stdoutStr, namespace, podName)
|
||||
} else if parseErr != nil {
|
||||
result.ExitCode = 1
|
||||
result.Error = a.buildErrorWithHelp(parseErr, stderrOutput.String(), namespace, podName)
|
||||
result.Error = a.buildErrorWithHelp(parseErr, stderrStr, stdoutStr, namespace, podName)
|
||||
} else if resultMsg != nil && !resultMsg.IsSuccess() {
|
||||
result.ExitCode = 1
|
||||
if resultMsg.Error != "" {
|
||||
result.Error = a.buildErrorWithHelp(fmt.Errorf("%s", resultMsg.Error), stderrOutput.String(), namespace, podName)
|
||||
result.Error = a.buildErrorWithHelp(fmt.Errorf("%s", resultMsg.Error), stderrStr, stdoutStr, namespace, podName)
|
||||
} else {
|
||||
result.Error = a.buildErrorWithHelp(nil, stderrOutput.String(), namespace, podName)
|
||||
result.Error = a.buildErrorWithHelp(nil, stderrStr, stdoutStr, namespace, podName)
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,8 +322,8 @@ func (a *Adapter) streamStderrCapture(r io.Reader, handler domain.AgentEventHand
|
||||
}
|
||||
}
|
||||
|
||||
// buildErrorWithHelp creates an error message with stderr output and troubleshooting help.
|
||||
func (a *Adapter) buildErrorWithHelp(err error, stderr, namespace, podName string) error {
|
||||
// buildErrorWithHelp creates an error message with captured output and troubleshooting help.
|
||||
func (a *Adapter) buildErrorWithHelp(err error, stderr, stdout, namespace, podName string) error {
|
||||
var msg strings.Builder
|
||||
|
||||
if err != nil {
|
||||
@ -330,6 +332,12 @@ func (a *Adapter) buildErrorWithHelp(err error, stderr, namespace, podName strin
|
||||
msg.WriteString("claude command failed")
|
||||
}
|
||||
|
||||
// Include stdout if it contains useful output (e.g. auth errors that Claude writes to stdout)
|
||||
if stdout != "" {
|
||||
msg.WriteString("\n\noutput:\n")
|
||||
msg.WriteString(stdout)
|
||||
}
|
||||
|
||||
// Include stderr if available
|
||||
if stderr != "" {
|
||||
msg.WriteString("\n\nstderr:\n")
|
||||
|
||||
@ -221,9 +221,15 @@ func (b *BuildExecutor) Execute(ctx context.Context, task *domain.WorkTask) *dom
|
||||
}
|
||||
}
|
||||
|
||||
// Use streamed output, but fall back to agent's captured output if streaming missed it
|
||||
output := outputBuilder.String()
|
||||
if output == "" && agentResult.FinalOutput != "" {
|
||||
output = agentResult.FinalOutput
|
||||
}
|
||||
|
||||
result := &domain.BuildResult{
|
||||
Success: agentResult.Success(),
|
||||
Output: outputBuilder.String(),
|
||||
Output: output,
|
||||
DurationMs: time.Since(start).Milliseconds(),
|
||||
Artifacts: make(map[string]string),
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user