Skip to content

Commit ebb7c02

Browse files
authored
retry net.ErrClosed by default (#2949)
1 parent 19d2a28 commit ebb7c02

File tree

3 files changed

+18
-0
lines changed

3 files changed

+18
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "b2213048-b0dd-4619-bd61-1e41eb07bcb0",
3+
"type": "bugfix",
4+
"description": "Retry transient net.ErrClosed errors by default.",
5+
"modules": [
6+
"."
7+
]
8+
}

aws/retry/retryable_error.go

+6
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,13 @@ func (r RetryableConnectionError) IsErrorRetryable(err error) aws.Ternary {
116116
case errors.As(err, &conErr) && conErr.ConnectionError():
117117
retryable = true
118118

119+
case strings.Contains(err.Error(), "use of closed network connection"):
120+
fallthrough
119121
case strings.Contains(err.Error(), "connection reset"):
122+
// The errors "connection reset" and "use of closed network connection"
123+
// are effectively the same. It appears to be the difference between
124+
// sync and async read of TCP RST in the stdlib's net.Conn read loop.
125+
// see #2737
120126
retryable = true
121127

122128
case errors.As(err, &urlErr):

aws/retry/retryable_error_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ func TestRetryConnectionErrors(t *testing.T) {
136136
Err: fmt.Errorf("some error %w", mockTimeoutError{b: true}),
137137
},
138138
},
139+
"net.ErrClosed": {
140+
Retryable: aws.TrueTernary,
141+
Err: net.ErrClosed,
142+
},
139143
}
140144

141145
for name, c := range cases {

0 commit comments

Comments
 (0)