fix: address PR review - Anthropic error format in panic recovery and nil guard

- Add recoverAnthropicMessagesPanic for Messages handler to return
  Anthropic-formatted errors instead of OpenAI Responses format on panic
- Add nil check for rateLimitService.HandleUpstreamError in
  ForwardAsAnthropic to match defensive pattern used elsewhere

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
alfadb
2026-03-06 15:40:15 +08:00
parent ff1f114989
commit bc194a7d8c
2 changed files with 24 additions and 2 deletions

View File

@@ -428,7 +428,7 @@ func (h *OpenAIGatewayHandler) logOpenAIRemoteCompactOutcome(c *gin.Context, sta
// POST /v1/messages (when group platform is OpenAI) // POST /v1/messages (when group platform is OpenAI)
func (h *OpenAIGatewayHandler) Messages(c *gin.Context) { func (h *OpenAIGatewayHandler) Messages(c *gin.Context) {
streamStarted := false streamStarted := false
defer h.recoverResponsesPanic(c, &streamStarted) defer h.recoverAnthropicMessagesPanic(c, &streamStarted)
requestStart := time.Now() requestStart := time.Now()
@@ -1157,6 +1157,26 @@ func (h *OpenAIGatewayHandler) recoverResponsesPanic(c *gin.Context, streamStart
) )
} }
// recoverAnthropicMessagesPanic recovers from panics in the Anthropic Messages
// handler and returns an Anthropic-formatted error response.
func (h *OpenAIGatewayHandler) recoverAnthropicMessagesPanic(c *gin.Context, streamStarted *bool) {
recovered := recover()
if recovered == nil {
return
}
started := streamStarted != nil && *streamStarted
requestLogger(c, "handler.openai_gateway.messages").Error(
"openai.messages_panic_recovered",
zap.Bool("stream_started", started),
zap.Any("panic", recovered),
zap.ByteString("stack", debug.Stack()),
)
if !started {
h.anthropicErrorResponse(c, http.StatusInternalServerError, "api_error", "Internal server error")
}
}
func (h *OpenAIGatewayHandler) ensureResponsesDependencies(c *gin.Context, reqLog *zap.Logger) bool { func (h *OpenAIGatewayHandler) ensureResponsesDependencies(c *gin.Context, reqLog *zap.Logger) bool {
missing := h.missingResponsesDependencies() missing := h.missingResponsesDependencies()
if len(missing) == 0 { if len(missing) == 0 {

View File

@@ -137,7 +137,9 @@ func (s *OpenAIGatewayService) ForwardAsAnthropic(
Message: upstreamMsg, Message: upstreamMsg,
Detail: upstreamDetail, Detail: upstreamDetail,
}) })
s.rateLimitService.HandleUpstreamError(ctx, account, resp.StatusCode, resp.Header, respBody) if s.rateLimitService != nil {
s.rateLimitService.HandleUpstreamError(ctx, account, resp.StatusCode, resp.Header, respBody)
}
return nil, &UpstreamFailoverError{StatusCode: resp.StatusCode, ResponseBody: respBody} return nil, &UpstreamFailoverError{StatusCode: resp.StatusCode, ResponseBody: respBody}
} }
// Non-failover error: return Anthropic-formatted error to client // Non-failover error: return Anthropic-formatted error to client