fix(providers): clear timeout error message and fallback on CLI provider timeout
When a CLI provider subprocess was killed due to request_timeout, the error
reported was the raw subprocess signal ("signal: killed"), giving the user
no indication that a timeout was the cause. Additionally, the fallback chain
would not trigger because ClassifyError used == to match context.DeadlineExceeded,
which does not match wrapped errors.
- Each CLI provider now checks ctx.Err() == context.DeadlineExceeded after
cmd.Run() fails and returns a descriptive error (e.g. "claude cli timed out
after 30s") that wraps context.DeadlineExceeded
- ClassifyError updated to use errors.Is instead of == when checking for
context.DeadlineExceeded, so wrapped timeout errors correctly classify as
FailoverTimeout and trigger fallback to the next candidate in the chain
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
df967fe63c
commit
56ac14c0e5
4 changed files with 11 additions and 1 deletions
|
|
@ -63,6 +63,9 @@ func (p *ClaudeCliProvider) Chat(
|
|||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return nil, fmt.Errorf("claude cli timed out after %s: %w", p.timeout, context.DeadlineExceeded)
|
||||
}
|
||||
stderrStr := strings.TrimSpace(stderr.String())
|
||||
stdoutStr := strings.TrimSpace(stdout.String())
|
||||
switch {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@ func (p *CodexCliProvider) Chat(
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return nil, fmt.Errorf("codex cli timed out after %s: %w", p.timeout, context.DeadlineExceeded)
|
||||
}
|
||||
if ctx.Err() == context.Canceled {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package providers
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
|
@ -114,7 +115,7 @@ func ClassifyError(err error, provider, model string) *FailoverError {
|
|||
}
|
||||
|
||||
// Context deadline exceeded: treat as timeout, always fallback.
|
||||
if err == context.DeadlineExceeded {
|
||||
if errors.Is(err, context.DeadlineExceeded) {
|
||||
return &FailoverError{
|
||||
Reason: FailoverTimeout,
|
||||
Provider: provider,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ func (p *GeminiCliProvider) Chat(
|
|||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return nil, fmt.Errorf("gemini cli timed out after %s: %w", p.timeout, context.DeadlineExceeded)
|
||||
}
|
||||
stderrStr := strings.TrimSpace(stderr.String())
|
||||
stdoutStr := strings.TrimSpace(stdout.String())
|
||||
switch {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue