refactor: replace direct error comparisons with errors.Is

Improves correctness when working with wrapped errors
This commit is contained in:
Ruslan Semagin 2026-02-19 07:51:46 +03:00
parent e8afd31b28
commit 4e68cf5b1e
10 changed files with 21 additions and 15 deletions

View file

@ -7,6 +7,7 @@ import (
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
@ -104,7 +105,7 @@ func (c *LINEChannel) Start(ctx context.Context) error {
"addr": addr,
"path": path,
})
if err := c.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
if err := c.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
logger.ErrorCF("line", "Webhook server error", map[string]interface{}{
"error": err.Error(),
})

View file

@ -5,6 +5,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"os/exec"
"strings"
@ -67,7 +68,7 @@ func (p *CodexCliProvider) Chat(ctx context.Context, messages []Message, tools [
}
if err != nil {
if ctx.Err() == context.Canceled {
if errors.Is(ctx.Err(), context.Canceled) {
return nil, ctx.Err()
}
if stderrStr := stderr.String(); stderrStr != "" {

View file

@ -91,8 +91,8 @@ func (p *CodexProvider) Chat(ctx context.Context, messages []Message, tools []To
if evt.Type == "response.completed" || evt.Type == "response.failed" || evt.Type == "response.incomplete" {
evtResp := evt.Response
if evtResp.ID != "" {
copy := evtResp
resp = &copy
cp := evtResp
resp = &cp
}
}
}

View file

@ -2,6 +2,7 @@ package providers
import (
"context"
"errors"
"regexp"
"strings"
)
@ -102,12 +103,12 @@ func ClassifyError(err error, provider, model string) *FailoverError {
}
// Context cancellation: user abort, never fallback.
if err == context.Canceled {
if errors.Is(err, context.Canceled) {
return nil
}
// Context deadline exceeded: treat as timeout, always fallback.
if err == context.DeadlineExceeded {
if errors.Is(err, context.DeadlineExceeded) {
return &FailoverError{
Reason: FailoverTimeout,
Provider: provider,

View file

@ -293,7 +293,7 @@ func TestFailoverError_ErrorString(t *testing.T) {
func TestFailoverError_Unwrap(t *testing.T) {
inner := errors.New("inner error")
fe := &FailoverError{Reason: FailoverTimeout, Wrapped: inner}
if fe.Unwrap() != inner {
if !errors.Is(inner, fe.Unwrap()) {
t.Error("Unwrap should return wrapped error")
}
}

View file

@ -2,6 +2,7 @@ package providers
import (
"context"
"errors"
"fmt"
"strings"
"time"
@ -98,7 +99,7 @@ func (fc *FallbackChain) Execute(
for i, candidate := range candidates {
// Check context before each attempt.
if ctx.Err() == context.Canceled {
if errors.Is(ctx.Err(), context.Canceled) {
return nil, context.Canceled
}
@ -130,7 +131,7 @@ func (fc *FallbackChain) Execute(
}
// Context cancellation: abort immediately, no fallback.
if ctx.Err() == context.Canceled {
if errors.Is(ctx.Err(), context.Canceled) {
result.Attempts = append(result.Attempts, FallbackAttempt{
Provider: candidate.Provider,
Model: candidate.Model,
@ -204,7 +205,7 @@ func (fc *FallbackChain) ExecuteImage(
}
for i, candidate := range candidates {
if ctx.Err() == context.Canceled {
if errors.Is(ctx.Err(), context.Canceled) {
return nil, context.Canceled
}
@ -219,7 +220,7 @@ func (fc *FallbackChain) ExecuteImage(
return result, nil
}
if ctx.Err() == context.Canceled {
if errors.Is(ctx.Err(), context.Canceled) {
result.Attempts = append(result.Attempts, FallbackAttempt{
Provider: candidate.Provider,
Model: candidate.Model,

View file

@ -122,7 +122,7 @@ func TestFallback_ContextCanceled(t *testing.T) {
}
_, err := fc.Execute(ctx, candidates, run)
if err != context.Canceled {
if !errors.Is(err, context.Canceled) {
t.Errorf("expected context.Canceled, got %v", err)
}
}

View file

@ -2,6 +2,7 @@ package tools
import (
"encoding/json"
"errors"
"fmt"
"syscall"
"unsafe"
@ -113,7 +114,7 @@ func (t *I2CTool) scan(args map[string]interface{}) *ToolResult {
// Set slave address — EBUSY means a kernel driver owns this address
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), i2cSlave, uintptr(addr))
if errno != 0 {
if errno == syscall.EBUSY {
if errors.Is(errno, syscall.EBUSY) {
found = append(found, deviceEntry{
Address: fmt.Sprintf("0x%02x", addr),
Status: "busy (in use by kernel driver)",

View file

@ -126,7 +126,7 @@ func TestMessageTool_Execute_SendFailure(t *testing.T) {
if result.Err == nil {
t.Error("Expected Err to be set")
}
if result.Err != sendErr {
if !errors.Is(sendErr, result.Err) {
t.Errorf("Expected Err to be sendErr, got %v", result.Err)
}
}

View file

@ -3,6 +3,7 @@ package tools
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
@ -188,7 +189,7 @@ func (t *ExecTool) Execute(ctx context.Context, args map[string]interface{}) *To
}
if err != nil {
if cmdCtx.Err() == context.DeadlineExceeded {
if errors.Is(cmdCtx.Err(), context.DeadlineExceeded) {
msg := fmt.Sprintf("Command timed out after %v", t.timeout)
return &ToolResult{
ForLLM: msg,