Skip to content

MCP tool returning MIME-mismatched image permanently poisons conversation (400 on all subsequent turns) #311732

@Wuyufan180

Description

@Wuyufan180

Bug Description

When an MCP tool (e.g., mcp_filesystem_read_media_file) returns a base64-encoded image with an incorrect MIME type declaration (declares image/png but the actual data is JPEG), the API returns a 400 error. More critically, this single error permanently corrupts the entire conversation — every subsequent message in that session fails with the same 400 error, regardless of content.

Steps to Reproduce

  1. Have a file with .png extension that actually contains JPEG-encoded data (common when images are saved/exported with wrong extension)
  2. In a Copilot Chat conversation, trigger an MCP tool that reads this image (e.g., mcp_filesystem_read_media_file)
  3. The tool returns base64 data with media_type: "image/png" but the actual bytes are JPEG
  4. First failure: API returns 400: "The image was specified using the image/png media type, but the image appears to be a image/jpeg image"
  5. Permanent failure: Every subsequent message in this conversation — even a simple "hello" — returns the same 400 error

Error Message

Request Failed: 400
{"message":"messages.32.content.0.tool_result.content.0.image.source.base64: The image was specified using the image/png media type, but the image appears to be a image/jpeg image"}

Root Cause

The malformed tool result (with mismatched MIME type) becomes part of the conversation history. Since every new turn sends the full history to the API, and the API validates all images in the history, every subsequent request fails on the same poisoned entry.

Expected Behavior

  1. Graceful error handling: The conversation should not become permanently unusable due to a single bad tool result
  2. MIME type detection: When an MCP tool returns image data, the system should validate/detect the actual image format rather than trusting the declared MIME type (JPEG starts with FF D8, PNG starts with 89 50 4E 47 — a 4-byte check is sufficient)
  3. Recovery mechanism: At minimum, the poisoned tool result should be stripped or corrected in subsequent turns so the conversation can continue

Workaround

  • The affected conversation cannot be recovered — user must start a new conversation
  • Convert the problematic image file to its correct format beforehand: PIL.Image.open(path).save(path, format='PNG')

Environment

  • VS Code: latest stable (April 2026)
  • GitHub Copilot Chat extension: 0.43.0
  • Model: Claude Opus 4.6 (likely affects all models with image validation)
  • OS: Windows 11
  • MCP tool involved: mcp_filesystem_read_media_file (filesystem MCP server)

Impact

This is particularly disruptive because:

  • Users lose all conversation context when forced to start a new session
  • The failure mode is confusing — users don't understand why even "hello" fails
  • JPEG files with .png extension are surprisingly common (screenshots, web downloads, exports from various tools)

Similar Issue

A similar bug was reported and fixed in another AI coding tool: anomalyco/opencode#15264 — "invalid image payload from file attachment poisons subsequent turns"

Suggested Fix

Either at the client level (VS Code extension) or server level:

# Detect actual format from magic bytes before sending to API
MAGIC = {b'\xff\xd8': 'image/jpeg', b'\x89PNG': 'image/png', b'GIF8': 'image/gif', b'RIFF': 'image/webp'}
actual_type = next((v for k, v in MAGIC.items() if data.startswith(k)), declared_type)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions