DeepSeek Harness image count limit 400: a session fix

TroubleshootingPublished 2026-10-20Author: DeepSeek Plugin Market
DeepSeek Harnessimages400INVALID_REQUESTllm-pi-aicontext
The adapter limits pixels and bytes per image but never counts them. After eight images accumulate in history, every request exceeds the endpoint limit.

A conversation accumulated a dozen screenshots. Early turns were fine, then every message started returning 400, and deleting the screenshot you just sent changed nothing. DeepSeek Harness (DSH) constrains image pixels and bytes but not the number of images, while the endpoint accepts at most eight per request. Because historical images are re-sent with the context, crossing that count wedges the whole session.

Count the DeepSeek Harness images that ride along every request

If the gallery in the session is large, every turn fails, and switching models or retrying changes nothing, assume the count limit before looking anywhere else. Verify with three checks:

  1. Total the attachments — count every image in the session, including screenshots and clipboard pastes; expected: the number is at or above eight, often higher than you remember.
  2. Send plain text — post a message without any new attachment; expected: if it also returns 400, history images are still being sent.
  3. Test a clean session — create one and attach a single image; expected: it succeeds, which rules out format or model capability problems.

According to the source review in the discussion, llm-pi-ai has pixel and byte limits at adapter.ts:410-415 and a request byte limit at config.ts:167-173, but no image-count check; stream.ts:48-49 maps the 400 to INVALID_REQUEST and leaves it outside the retry list (#9981). For normal image capability setup, see model image capability.

Why deleting the newest DSH image changes nothing

The request is built from the whole context, so the images that push you over the limit are the old ones, not the one you just removed. Follow the assembly:

  • Messages are grouped by turn — DSH builds each request from the stored history, so every image-bearing round is included.
  • Attachments become parts — each round contributes its image parts, and nothing is dropped by age.
  • The endpoint counts the total — it evaluates the entire request, not the newest turn.
  • Any overage rejects the turn — once the total passes eight, even a one-word message returns 400.
  • Removing one image is not enough — the remaining history still exceeds the limit, so the failure persists.

Three DeepSeek Harness fixes for the image count limit

Bottom line: prune history for an occasional overflow, add an adapter cap when the team pastes screenshots daily, and rebuild a lean session when the transcript has little value.

Repair 1: prune image parts from history

Without a plugin or a code change, the direct route is to replace old attachments with text while keeping the most recent ones. Work from the oldest rounds:

  1. Back up the session — copy the session directory so the edit is reversible; expected: you can restore the original state.
  2. Replace old images — from the earliest image-bearing round, substitute a text note such as "screenshot: error was X"; expected: the image part is gone and the message remains.
  3. Check after each batch — send a plain-text message following every batch; expected: no more 400.
  4. Keep the recent context — preserve images from the last two or three rounds; expected: the model still understands the current task.
  5. Externalise what matters — save key screenshots into the workspace and reference their paths; expected: the information survives without inline images.

Repair 2: add an oldest-first image cap to the adapter

The durable fix is a counting predicate in toPiContext's replacement loop, so the request is trimmed before it is sent.

  1. Count in the assembly step — in adapter.ts:407, total the image parts while building the context; expected: the count is known before serialization.
  2. Apply a maximum — when the count exceeds maxImages, replace the oldest images with text placeholders; expected: the request stays within the limit.
  3. Make the cap configurable — expose it at provider level instead of hard-coding eight; expected: endpoints with different limits can be supported.
  4. Log the trimming — record how many images were dropped; expected: the behaviour is visible to the user.
  5. Test the boundaries — cover seven, eight, and twelve images; expected: each case behaves predictably.
StrategyAdvantageDrawback
Drop oldestKeeps recent context, good for ongoing debuggingOld evidence disappears
Drop non-essentialSmaller information lossNeeds rules about type or origin
Convert all to textLowest token costVisual detail is lost entirely

Repair 3: rebuild a lean session

When the old session is dominated by images and cleanup would take longer than restarting, migrate the conclusions and a couple of screenshots.

  1. Export the state — copy the last few rounds of conclusions and open tasks; expected: the decisions are captured as text.
  2. Create a new session — paste the background and attach only one or two key images; expected: the request starts well below the limit.
  3. Probe first — send plain text, then an image request; expected: both return 200.
  4. Archive the old session — keep it out of the recent list; expected: it is not reopened and does not fail again by accident.

Verify DSH fixes and avoid regressions

Prove that the request now carries no more than the allowed number of images and that trimming preserves the recent ones. Check:

  1. Replay a heavy session — construct one with twelve images and send a turn; expected: eight images are sent and no 400 appears.
  2. Inspect the trimming order — confirm the oldest images were replaced; expected: the most recent key images remain.
  3. Send plain text — verify a text-only turn; expected: history no longer fails because of image count.
  4. Switch models — repeat the request on another model; expected: the counting behaviour is provider-independent.

Avoid these traps:

  • Do not read the 400 as a key or quota problem; an image-count rejection carries no quota wording.
  • Compaction does not delete images automatically, so prune explicitly.
  • Endpoint limits differ, so keep maxImages configurable rather than hard-coded.
  • No official fix version is named; 0.2.1-rc.2 still reproduces, so check release notes and do not read an old DSH plugin behavior as current.
  • Replace, do not delete messages: removing an entire message can break tool_use and tool_result pairing.

DeepSeek Harness image 400 FAQ

Q: Why does DeepSeek Harness return 400 after several images even when I delete the last one? A: DeepSeek Harness returns 400 because the limit counts images across the whole request, not the last turn. Older images are still sent with the context, so the total stays above eight until some history is removed or the adapter prunes images before sending.

Q: Why does DeepSeek Harness still hit an image limit when maxPixels and maxBytes are set? A: DeepSeek Harness maxPixels and maxBytes constrain each image's pixels and bytes, not the number of images. Eight small images pass the size checks while the total still exceeds the server limit; the adapter has no counting predicate, so it sends the oversized request unchanged.

Q: Why is the DeepSeek Harness image 400 never retried, and why does switching models fail? A: The DeepSeek Harness image 400 maps to INVALID_REQUEST, which is not on the default retry list, and a different model still receives the same history images. Recovery requires reducing the image count or moving to an endpoint with a higher limit.

Q: How do I make an old DeepSeek Harness session usable without losing important images? A: An old DeepSeek Harness session can be made usable by saving the key images into the workspace and replacing them with text, then stripping attachments from the oldest non-essential rounds. A lean new session with the conclusions and a couple of images also works.

FAQ

Why does DeepSeek Harness return 400 after several images even when I delete the last one?

DeepSeek Harness returns 400 because the limit counts images across the whole request, not the last turn. Older images are still sent with the context, so the total stays above eight until some history is removed or the adapter prunes images before sending.

Why does DeepSeek Harness still hit an image limit when maxPixels and maxBytes are set?

DeepSeek Harness maxPixels and maxBytes constrain each image's pixels and bytes, not the number of images. Eight small images pass the size checks while the total still exceeds the server limit; the adapter has no counting predicate, so it sends the oversized request unchanged.

Why is the DeepSeek Harness image 400 never retried, and why does switching models fail?

The DeepSeek Harness image 400 maps to INVALID_REQUEST, which is not on the default retry list, and a different model still receives the same history images. Recovery requires reducing the image count or moving to an endpoint with a higher limit.

How do I make an old DeepSeek Harness session usable without losing important images?

An old DeepSeek Harness session can be made usable by saving the key images into the workspace and replacing them with text, then stripping attachments from the oldest non-essential rounds. A lean new session with the conclusions and a couple of images also works.

Related Terms

maxRequestImageBytes
maxRequestImageBytes is a DeepSeek Harness limit on the total bytes of images in one request. It is a size constraint, so it does not stop many small images from exceeding the server's count limit.— https://github.com/deepseek-ai/deepseek-harness/discussions/9981
INVALID_REQUEST
INVALID_REQUEST is the unified mapping DSH applies to an upstream 400, meaning the request itself is invalid. It is not retried by default because resending identical content usually repeats the result.— https://github.com/deepseek-ai/deepseek-harness/discussions/9981
oldest-first
oldest-first is the replacement order DSH uses when assembling image context, evicting the oldest image first. The replacement loop exists, but it lacks a ceiling on the total number of images.— https://github.com/deepseek-ai/deepseek-harness/discussions/9981

Sources