Commit bc194a7d authored by alfadb's avatar alfadb
Browse files

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: default avatarClaude Opus 4.6 <noreply@anthropic.com>
parent ff1f1149
...@@ -428,7 +428,7 @@ func (h *OpenAIGatewayHandler) logOpenAIRemoteCompactOutcome(c *gin.Context, sta ...@@ -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 ...@@ -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 {
......
...@@ -137,7 +137,9 @@ func (s *OpenAIGatewayService) ForwardAsAnthropic( ...@@ -137,7 +137,9 @@ func (s *OpenAIGatewayService) ForwardAsAnthropic(
Message: upstreamMsg, Message: upstreamMsg,
Detail: upstreamDetail, Detail: upstreamDetail,
}) })
if s.rateLimitService != nil {
s.rateLimitService.HandleUpstreamError(ctx, account, resp.StatusCode, resp.Header, respBody) 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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment