From a095465852dd8a707413b7548e83f65660cb65be Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 21 Jun 2026 03:11:40 +0000 Subject: [PATCH] fix(assistant): handle gif URLs breaking vision responses A gif URL in a message was matched by the image URL regex and sent to the vision API, which returned a 400 "Error while downloading ...gif" (the API cannot process animated gifs), failing the entire response. - Exclude gif from the image URL regex to match the attachment handler, which already skipped gif. - Strip images and retry on "Error while downloading" in the BadRequestError handler so any unfetchable image URL degrades gracefully. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_011vjHtN5hcQi9hGonuDbMEG --- assistant/CHANGELOG.md | 4 ++++ assistant/common/chat.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/assistant/CHANGELOG.md b/assistant/CHANGELOG.md index 43ef00c5c..a21101d0b 100644 --- a/assistant/CHANGELOG.md +++ b/assistant/CHANGELOG.md @@ -1,5 +1,9 @@ # Assistant Changelog +## v8.18.3 + +- **Fix**: A gif URL in a message no longer breaks the response. Gif URLs were matched and sent to the vision API, which returned a 400 `Error while downloading ...gif` (the API can't process animated gifs). Excluded gif from the image URL regex to match the attachment handler (which already skipped gif), and the `BadRequestError` handler now also strips images and retries on `Error while downloading` so any unfetchable image URL degrades gracefully instead of failing the whole reply. + ## v8.18.2 - **Fix**: `[p]assistant backup` no longer wipes live conversations. It excluded conversation data by clearing `self.db.conversations` on the real in-memory store; with per-file persistence that also caused the on-disk files to be overwritten on next use. Now excludes conversations from the dump non-destructively via `model_dump_json(exclude=...)`. diff --git a/assistant/common/chat.py b/assistant/common/chat.py index 193c286f5..494e9e586 100644 --- a/assistant/common/chat.py +++ b/assistant/common/chat.py @@ -567,7 +567,10 @@ async def handle_message( outputfile_pattern = r"--outputfile\s+([^\s]+)" extract_pattern = r"--extract" get_last_message_pattern = r"--last" - image_url_pattern = r"(https?:\/\/\S+\.(?:png|gif|webp|jpg|jpeg)(?:\?\S*)?)" + # NOTE: gif is intentionally excluded. The vision API cannot process (animated) gifs and + # responds with a 400 "Error while downloading" which breaks the response. This mirrors the + # attachment handling below which also excludes gif. + image_url_pattern = r"(https?:\/\/\S+\.(?:png|webp|jpg|jpeg)(?:\?\S*)?)" # Extract the optional arguments and their values outputfile_match = re.search(outputfile_pattern, question) @@ -1054,7 +1057,10 @@ async def _get_chat_response( continue raise e except openai.BadRequestError as e: - if "Invalid image" in str(e): + err_text = str(e) + # Some image URLs (e.g. gifs, or links the API can't fetch) cause a 400. Rather than + # failing the whole response, strip images from the payload and retry without them. + if "Invalid image" in err_text or "Error while downloading" in err_text: await purge_images(messages) tries += 1 continue