Skip to content

webp/gif read via built-in Read-image tool 400s on kimi-for-coding and permanently deadlocks the session (failed image re-sent every turn) #1082

Description

@fanzhe47

Summary

A single webp (or gif) image that is pulled into the conversation by the built-in Read image file tool makes every subsequent LLM request fail with a non-retryable 400 ... failed to decode image, and because the failed image stays in history and is re-sent on every turn, the session is permanently deadlocked — no prompt can ever make progress again.

The image MIME is sniffed correctly (image/webp / image/gif), so this is not a mislabeling bug. The kimi-for-coding endpoint simply rejects these formats, and kimi-code has no guard, no transcode, and no way to drop the offending image from context.

Environment

  • kimi-code 0.18.0 (observed). The 0.19.2 changelog does not appear to address the failed-image / history-resend path, but I have not re-verified on 0.19.2.
  • Model: kimi-for-coding (Kimi-k2.6)
  • macOS (arm64)
  • Driven headlessly by an ACP client in --yolo mode (non-interactive), though the same mechanism applies to any harness.

What happens

The agent, during a normal task, calls the built-in Read image file tool on a local asset that happens to be a webp (saved with a misleading .png filename) and a small gif:

tool.result:
  <system>Read image file. Mime type: image/webp. Size: 83184 bytes ...</system>
  <image path=".../original_imgs/article2_img07.png">
  image_url: blobref:image/webp;<hash>

The very next LLM request fails:

WARN  llm request failed  turnStep=2.26 attempt=1/3 model=kimi-for-coding
      errorName=APIStatusError statusCode=400
      errorMessage="400 Invalid request: prepare image failed error, status code: 400,
                    message: failed to decode image: invalid or unsupported image format"
ERROR turn failed  turnId=2
WARN  acp: turn ended with failed reason  ... "retryable":false

From that point on, every turn fails immediately with the identical error:

turn failed  turnId=2   (step 2.26, when the image entered context)
turn failed  turnId=3
turn failed  turnId=4
turn failed  turnId=5   (sending "?" — anything — just triggers another doomed request)

The conversation contained 28 images total; 23 PNG + 2 JPEG decoded fine. The only failing inputs were 2 GIF + 1 WebP, all of them sniffed and labeled correctly as image/gif / image/webp.

Root cause (two compounding problems)

  1. No format guard before sending to the vision endpoint. The Read-image tool forwards image/webp and image/gif to kimi-for-coding, which returns 400 failed to decode image. (Note: the general Kimi Vision docs list webp/gif as supported, but kimi-for-coding clearly does not accept them — an inconsistency worth confirming on the server side. Either way, kimi-code should transcode to png/jpeg, or refuse to attach, instead of poisoning the turn.)

  2. A non-retryable image error permanently wedges the session. Because the failed image remains in history and is re-sent on every following request, turns 3/4/5/... can never succeed — there is no recovery short of starting a brand-new session or hand-editing wire.jsonl. This is the same family as #2279 (historical images re-sent) and Pasted images fail on text-only models — should offload to file + MCP path #905 (no offload fallback), but here it is triggered by the built-in Read-image tool on a server-rejected format, not by a text-only model or a web-session restore.

Expected behavior

Any one of these would break the deadlock:

  • Before attaching, check the active model's accepted formats and transcode webp/gif → png/jpeg (or downscale) when needed.
  • If the endpoint returns a non-retryable image-decode 400, drop the offending image from context (replace with a text note like [image omitted: unsupported format]) and let the turn proceed, instead of re-sending it forever.
  • Surface the failure to the user/harness as a recoverable condition rather than an infinite identical-error loop.

Steps to reproduce

  1. Put a .png-named file that is actually webp bytes (any web-downloaded webp) in the working dir, plus a small .gif.
  2. Ask the agent to read/analyze those images with kimi-for-coding as the model.
  3. Observe the 400 failed to decode image (non-retryable).
  4. Send any further message → it fails immediately with the same error. The session never recovers.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions