From 4467a60298e44c355307a79fd36cd29a4ad1abce Mon Sep 17 00:00:00 2001 From: XianYuDaXian Date: Wed, 18 Mar 2026 13:35:51 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20media=5Fpost=20?= =?UTF-8?q?=E7=9A=84=20KeyError=20=E6=97=A5=E5=BF=97=E5=86=B2=E7=AA=81?= =?UTF-8?q?=E5=8F=8A=20video=20401=20=E8=87=AA=E5=8A=A8=E6=8D=A2=20token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/grok/services/video.py | 27 +++++++++++++++++++++++---- app/services/reverse/media_post.py | 15 +++++++++------ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/app/services/grok/services/video.py b/app/services/grok/services/video.py index 6ae2476..5d44292 100644 --- a/app/services/grok/services/video.py +++ b/app/services/grok/services/video.py @@ -1360,6 +1360,21 @@ class VideoService: # Process response. if is_stream: + try: + stream_iter = response.__aiter__() + # 诱发初始请求,若发生 401 等异常,将在 completions 的 try 块内被捕捉。 + first_chunk = await stream_iter.__anext__() + except StopAsyncIteration: + first_chunk = None + + async def _merged_stream(first, remaining): + if first is not None: + yield first + async for chunk in remaining: + yield chunk + + combined_response = _merged_stream(first_chunk, stream_iter) + processor = VideoStreamProcessor( model, token, @@ -1368,7 +1383,7 @@ class VideoService: idle_timeout_override=None, ) return wrap_stream_with_usage( - processor.process(response), token_mgr, token, model + processor.process(combined_response), token_mgr, token, model ) result = await VideoCollectProcessor( @@ -1394,10 +1409,14 @@ class VideoService: except UpstreamException as e: last_error = e - if rate_limited(e): - await token_mgr.mark_rate_limited(token) + status_code = e.details.get("status") if e.details else getattr(e, "status_code", None) + if rate_limited(e) or status_code == 401: + if rate_limited(e): + await token_mgr.mark_rate_limited(token) + else: + await token_mgr.record_fail(token, status_code, "video_auth_failed_401") logger.warning( - f"Token {_token_tag(token)} rate limited (429), " + f"Token {_token_tag(token)} {'rate limited (429)' if rate_limited(e) else 'auth failed (401)'}, " f"trying next token (attempt {attempt + 1}/{max_token_retries})" ) continue diff --git a/app/services/reverse/media_post.py b/app/services/reverse/media_post.py index 987e188..9819b2e 100644 --- a/app/services/reverse/media_post.py +++ b/app/services/reverse/media_post.py @@ -243,8 +243,9 @@ class MediaPostReverse: if len(content) > 300: content = f"{content[:300]}...(len={len(content)})" logger.error( - "MediaPostReverse: Media post create failed, " - f"status={response.status_code}, body={content or '-'}", + "MediaPostReverse: Media post create failed, status={}, body={}", + response.status_code, + content or '-', extra={"error_type": "UpstreamException"}, ) raise UpstreamException( @@ -342,8 +343,9 @@ class MediaPostReverse: if len(content) > 300: content = f"{content[:300]}...(len={len(content)})" logger.error( - "MediaPostReverse: Media post get failed, " - f"status={response.status_code}, body={content or '-'}", + "MediaPostReverse: Media post get failed, status={}, body={}", + response.status_code, + content or '-', extra={"error_type": "UpstreamException"}, ) raise UpstreamException( @@ -442,8 +444,9 @@ class MediaPostReverse: if len(content) > 300: content = f"{content[:300]}...(len={len(content)})" logger.error( - "MediaPostReverse: Media post create-link failed, " - f"status={response.status_code}, body={content or '-'}", + "MediaPostReverse: Media post create-link failed, status={}, body={}", + response.status_code, + content or '-', extra={"error_type": "UpstreamException"}, ) raise UpstreamException(