Skip to content

Commit d13541e

Browse files
committed
modelerrors: promote retryable/non-retryable patterns to package-level vars
The retryablePatterns and nonRetryablePatterns slices were local variables inside isRetryableModelError, causing a new allocation on every call. Promote them to package-level vars (like contextOverflowPatterns) so they are allocated once. Assisted-By: docker-agent
1 parent f182f8d commit d13541e

1 file changed

Lines changed: 37 additions & 40 deletions

File tree

pkg/modelerrors/modelerrors.go

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,43 @@ func IsRetryableStatusCode(statusCode int) bool {
213213
}
214214
}
215215

216+
// retryablePatterns contains error message substrings that indicate a
217+
// transient/retryable failure. Numeric status codes (500, 502, etc.) are
218+
// handled separately by ExtractHTTPStatusCode + IsRetryableStatusCode.
219+
var retryablePatterns = []string{
220+
"timeout", // Generic timeout
221+
"connection reset", // Connection reset
222+
"connection refused", // Connection refused
223+
"no such host", // DNS failure
224+
"temporary failure", // Temporary failure
225+
"service unavailable", // Service unavailable
226+
"internal server error", // Server error
227+
"bad gateway", // Gateway error
228+
"gateway timeout", // Gateway timeout
229+
"overloaded", // Server overloaded
230+
"overloaded_error", // Server overloaded
231+
"other side closed", // Connection closed by peer
232+
"fetch failed", // Network fetch failure
233+
"reset before headers", // Connection reset before headers received
234+
"upstream connect", // Upstream connection error
235+
"internal_error", // HTTP/2 INTERNAL_ERROR (stream-level)
236+
}
237+
238+
// nonRetryablePatterns contains error message substrings that indicate a
239+
// permanent/non-retryable failure. Numeric status codes (429, 401, etc.) are
240+
// handled separately by ExtractHTTPStatusCode.
241+
var nonRetryablePatterns = []string{
242+
"rate limit", // Rate limit message
243+
"too many requests", // Rate limit message
244+
"throttl", // Throttling (rate limiting)
245+
"quota", // Quota exceeded
246+
"capacity", // Capacity issues (often rate-limit related)
247+
"invalid", // Invalid request
248+
"unauthorized", // Auth error
249+
"authentication", // Auth error
250+
"api key", // API key error
251+
}
252+
216253
// isRetryableModelError determines if an error should trigger a retry of the SAME model.
217254
// It is used as a fallback by ClassifyModelError when no *StatusError is present.
218255
//
@@ -268,55 +305,15 @@ func isRetryableModelError(err error) bool {
268305
}
269306
}
270307

271-
// Fall back to message-pattern matching for errors without structured status codes
272308
errMsg := strings.ToLower(err.Error())
273309

274-
// Retryable patterns (timeout, network issues)
275-
// NOTE: Numeric status codes (500, 502, etc.) are already handled by
276-
// ExtractHTTPStatusCode + IsRetryableStatusCode above; they are not
277-
// duplicated here to avoid false positives on arbitrary numbers in
278-
// error messages (e.g., "processed 500 items").
279-
retryablePatterns := []string{
280-
"timeout", // Generic timeout
281-
"connection reset", // Connection reset
282-
"connection refused", // Connection refused
283-
"no such host", // DNS failure
284-
"temporary failure", // Temporary failure
285-
"service unavailable", // Service unavailable
286-
"internal server error", // Server error
287-
"bad gateway", // Gateway error
288-
"gateway timeout", // Gateway timeout
289-
"overloaded", // Server overloaded
290-
"overloaded_error", // Server overloaded
291-
"other side closed", // Connection closed by peer
292-
"fetch failed", // Network fetch failure
293-
"reset before headers", // Connection reset before headers received
294-
"upstream connect", // Upstream connection error
295-
"internal_error", // HTTP/2 INTERNAL_ERROR (stream-level)
296-
}
297-
298310
for _, pattern := range retryablePatterns {
299311
if strings.Contains(errMsg, pattern) {
300312
slog.Debug("Matched retryable error pattern", "pattern", pattern)
301313
return true
302314
}
303315
}
304316

305-
// Non-retryable patterns (skip to next model immediately)
306-
// NOTE: Numeric status codes (429, 401, etc.) are already handled by
307-
// ExtractHTTPStatusCode above; they are not duplicated here.
308-
nonRetryablePatterns := []string{
309-
"rate limit", // Rate limit message
310-
"too many requests", // Rate limit message
311-
"throttl", // Throttling (rate limiting)
312-
"quota", // Quota exceeded
313-
"capacity", // Capacity issues (often rate-limit related)
314-
"invalid", // Invalid request
315-
"unauthorized", // Auth error
316-
"authentication", // Auth error
317-
"api key", // API key error
318-
}
319-
320317
for _, pattern := range nonRetryablePatterns {
321318
if strings.Contains(errMsg, pattern) {
322319
slog.Debug("Matched non-retryable error pattern", "pattern", pattern)

0 commit comments

Comments
 (0)