{"record":{"id":"837169282c8e74ea","repo":"fish2018/pansou","slug":"d-w-837169","errorCode":null,"errorMessage":"重试 %d 次后仍然失败: %w","messagePattern":"重试 (.+?) 次后仍然失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/ash/ash.go","lineNumber":304,"sourceCode":"\t\tif err == nil && resp.StatusCode == 200 {\n\t\t\treturn resp, nil\n\t\t}\n\t\t\n\t\t// 清理响应\n\t\tif resp != nil {\n\t\t\tresp.Body.Close()\n\t\t}\n\t\t\n\t\tlastErr = err\n\t\t\n\t\t// 如果是上下文取消或超时，不再重试\n\t\tif req.Context().Err() != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\t\n\tif lastErr != nil {\n\t\treturn nil, fmt.Errorf(\"重试 %d 次后仍然失败: %w\", maxRetries, lastErr)\n\t}\n\t\n\treturn nil, fmt.Errorf(\"重试 %d 次后仍然失败\", maxRetries)\n}\n\n","sourceCodeStart":286,"sourceCodeEnd":310,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/ash/ash.go#L286-L310","documentation":"ash's doRequestWithRetry loops until the request succeeds, maxRetries is hit, or the request context is cancelled. After the loop, if lastErr is non-nil it returns '重试 %d 次后仍然失败: %w' with the final transport error wrapped. This variant carries the root cause; the plain variant (error 38) fires only when the loop exited via context cancellation without recording lastErr.","triggerScenarios":"All retry attempts of the GET request fail (connection refused/reset, DNS, TLS, timeout) so lastErr is set when the loop ends, or the context expires with a last attempt error present — ash.go:304.","commonSituations":"Upstream fully unreachable (site down, blocked IP); every attempt hits the 15s context deadline; persistent 5xx handled as retryable errors inside the loop.","solutions":["Unwrap lastErr to identify the transport failure mode before changing settings.","Verify reachability of the ASH host with curl from the deployment environment.","Increase maxRetries/backoff or the context timeout if failures are intermittent/slow.","Add proxy or IP rotation if the site blocks the current egress address."],"exampleFix":"// before\nreturn nil, fmt.Errorf(\"重试 %d 次后仍然失败: %w\", maxRetries, lastErr)\n// after\nreturn nil, fmt.Errorf(\"重试 %d 次后仍然失败(%s): %w\", maxRetries, classifyNetErr(lastErr), lastErr)","handlingStrategy":"retry","validationCode":"func isRetryable(err error) bool { var ne net.Error; return errors.As(err, &ne) || errors.Is(err, syscall.ECONNREFUSED) }","typeGuard":null,"tryCatchPattern":"if err != nil {\n    cause := errors.Unwrap(err)\n    if isConnRefused(cause) { failFast() } else if isTimeout(cause) { retryWithLongerDeadline() }\n}","preventionTips":["Confirm upstream reachability from the deployment network before jobs","Keep retry budget within the caller's context deadline","Rotate egress IP/proxy when blocked","Log the wrapped transport error, never discard it"],"tags":["network","http","retry-exhausted","go"],"backgroundTag":"http-request-failed","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}