@@ -144,6 +144,38 @@ func TestManager_ShouldRetryAfterError_RetriesUnexpectedEOF(t *testing.T) {
144144 }
145145}
146146
147+ func TestManager_ShouldRetryAfterError_StatusBearingEOFUsesCooldownPath (t * testing.T ) {
148+ m := NewManager (nil , nil , nil )
149+ m .SetRetryConfig (3 , 30 * time .Second , 0 )
150+
151+ model := "test-model"
152+ // MarkResult applies a one-minute cooldown for transient 5xx responses.
153+ next := time .Now ().Add (time .Minute )
154+ auth := & Auth {
155+ ID : "auth-1" ,
156+ Provider : "claude" ,
157+ ModelStates : map [string ]* ModelState {
158+ model : {
159+ Unavailable : true ,
160+ Status : StatusError ,
161+ NextRetryAfter : next ,
162+ },
163+ },
164+ }
165+ if _ , errRegister := m .Register (context .Background (), auth ); errRegister != nil {
166+ t .Fatalf ("register auth: %v" , errRegister )
167+ }
168+
169+ _ , _ , maxWait := m .retrySettings ()
170+ // A 5xx whose body merely contains "unexpected EOF" must NOT take the
171+ // immediate fast path; with a single cooled-down credential and a cooldown
172+ // exceeding max-retry-interval, the cooldown-aware path declines the retry.
173+ statusErr := & Error {HTTPStatus : 500 , Message : "internal error: unexpected EOF" }
174+ if wait , shouldRetry := m .shouldRetryAfterError (statusErr , 0 , []string {"claude" }, model , maxWait ); shouldRetry {
175+ t .Fatalf ("expected shouldRetry=false for status-bearing EOF beyond cooldown, got true (wait=%v)" , wait )
176+ }
177+ }
178+
147179func TestManager_ShouldRetryAfterError_UnexpectedEOFRespectsRetryDisabled (t * testing.T ) {
148180 m := NewManager (nil , nil , nil )
149181 m .SetRetryConfig (0 , 30 * time .Second , 0 )
0 commit comments