Skip to content

[Bug]: Image with a .png name but JPEG content is stored as image/png; Anthropic rejects it with 400 on every later turn #16658

Open

Description

@JeongCheolLee

What happened?

Uploading an image whose file extension does not match its actual encoding (most commonly a JPEG saved as photo.png, which browsers' "Save image as", messengers and some screenshot tools produce) breaks the conversation for Anthropic models. The first request fails with:

messages.0.content.2.image.source.base64: The image was specified using the image/png media type, but the image appears to be a image/jpeg image

Because the image stays in the conversation history, every later message in that conversation fails with the same 400. OpenAI and Google models accept the same file, so it only surfaces with Claude.

Expected: the stored image is actually in imageOutputType, or at least the request declares the real media type.

Cause: uploaded images are converted to imageOutputType (default png), but whether the file is already in that format is decided from the file extension only:

  • api/server/services/Files/Local/images.js:53 — if (extension.toLowerCase() === targetExtension)
  • api/server/services/Files/images/convert.js:45 — same check (Firebase/Azure and packages/api/src/storage/images.ts follow the same pattern)

So a JPEG named .png skips conversion (resizeImageBuffer keeps the input format), is written as JPEG bytes, and the file record gets type: image/png. packages/api/src/files/encode/image.ts then sends file.type as the data URL type / Anthropic media_type.

Version Information

Reproduced on a fork based on v0.8.8-rc1 (Docker, built from source, fileStrategy: local, default imageOutputType). I did not reproduce on a clean upstream build, but the code above is unchanged on main at f10b1d9.

Steps to Reproduce

  1. Create a JPEG and give it a .png name, e.g.
    node -e "require('sharp')({create:{width:320,height:200,channels:3,background:'#d22'}}).jpeg().toFile('fake.png')"
    (file fake.png reports JPEG image data)
  2. Select any Anthropic model (agents endpoint).
  3. Attach fake.png with the file upload button (not paste — pasted images are re-encoded by the browser).
  4. Send any message: 400 as above. Send another message in the same conversation: same 400.
  5. The same file with an OpenAI or Google model works.

What browsers are you seeing the problem on?

Chrome

Relevant log output

litellm.BadRequestError: AnthropicException - b'{"type":"error","error":{"type":"invalid_request_error","message":"messages.0.content.1.image.source.base64: The image was specified using the image/png media type, but the image appears to be a image/jpeg image"}}'

(Our deployment routes through a LiteLLM proxy, hence the wrapper; the Anthropic error itself is the same.)

Screenshots

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

I have a fix running on our fork and would like to take this one if that works for you. The approach: (1) on upload, skip conversion only when both the extension and the actual format (sharp metadata) match imageOutputType; (2) when encoding, read the real type from the leading bytes and use it for the data URL / media_type, so conversations that already contain a mislabeled image recover too. Happy to adjust if you prefer only one of the two.

Activity

  1. added
    🐛 bugSomething isn't working
    🗺️ File Storagecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    🗺️ Server Corecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    on Oct 2, 2026
  2. JeongCheolLee commented on Oct 6, 2026

    @JeongCheolLee
    ContributorAuthor

    Opened #16806 against dev.

    It completes #15606 for the upload path — resizeImageBuffer has reported the real media type since then, and the upload strategies were discarding it in favour of the file extension — and settles the provider-facing type from the bytes in encodeAndFormatImages, so conversations that already hold a mislabeled image recover on their next turn instead of staying broken.

  3. added
    🗺️ Platform Securitycodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    🗺️ Core Infra & Seccodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)
    on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐛 bugSomething isn't working🗺️ Core Infra & Seccodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)🗺️ File Storagecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)🗺️ Platform Securitycodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)🗺️ Server Corecodegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions