
最近在 Claude Code 裡遇到一個讓人懵的錯:
An image in the conversation exceeds the dimension limit for many-image requests (2000px). Start a new session with fewer images.
我當時貼的是一張完全正常的 100×200 小圖。按直覺這應該是"最後那張圖超大",但實際不是。這是一個累積性 bug,觸發時機、原因、解法都反直覺,一旦踩到還會反覆踩。這篇文章把規則、原理、可直接用的工具都講清楚。
現象
一次典型觸發路徑:
- 某個 Claude Code 會話裡,你聊了半天,中途貼過幾張截圖(假設有一張是 2500×1800,Retina 截圖很容易超過 2000 px)。
- 繼續往下聊,又貼了一張新的截圖(不管多大)。
- 這次請求 直接失敗,報上面那個 dimension limit。
- 之後你純文字發訊息也會失敗。會話徹底卡住,除了開新會話沒別的選項。
如果你用的是 Paseo(多 tab 聚合 Claude Code / Codex 的客戶端),一個 tab 掛掉不影響別的,但那個 tab 裡一整段有價值的上下文基本就廢了。
原因:Anthropic API 的多圖分檔規則
Anthropic 的 Messages API 對圖片有兩檔尺寸規則:
| 請求裡的圖片數 | 單張圖最大尺寸 |
|---|---|
| 1 張(單圖模式) | 最大 8000×8000 |
| ≥ 2 張(多圖模式) | 每張每邊必須 ≤ 2000 px |
這裡的關鍵是**“請求裡的圖片數”**,而不是"你這次訊息帶的圖片數"。Claude Code(以及任何相容客戶端)的工作方式是:每次請求都把整個對話歷史——包括歷史所有圖片——作為 context 重新傳送。所以:
- 你第一次貼一張 2500×1800 的圖,單圖模式,OK。
- 你第二次再貼任何一張圖,哪怕是 50×50 的一個 emoji 截圖,這次請求裡就有 2 張圖,多圖模式觸發。回頭檢查歷史,第一張那 2500 寬的違反 2000 px 規則,整個請求被拒絕。
- 之後你哪怕不貼圖,只發文字,歷史裡那 2 張圖仍然在 context 裡,請求依然被拒絕。
所以這不是"最後那張圖有問題",而是"從第 2 張圖開始,歷史裡任何一張超過 2000 px 都會掛掉整個會話"。
Retina 顯示器截圖天然容易超標:標準 MacBook 3x 縮放下,一張顯示尺寸 800×600 的視窗截圖實際畫素是 2400×1800——已經過線。
基礎解法:剝離 JSONL 裡的 base64 圖片
Claude Code 把每個會話存成 JSON Lines:~/.claude/projects/<project-slug>/<session-uuid>.jsonl。每一行是一條訊息,圖片以 base64 形式嵌在訊息裡,類似:
{
"role": "user",
"content": [
{ "type": "text", "text": "看看這個報錯" },
{ "type": "image", "source": { "type": "base64", "data": "iVBORw0...巨長的 base64..." } }
]
}
救援思路很簡單:把 source 替換成佔位符,base64 不再嵌在 context 裡,多圖規則不再觸發。你的 prompt 文字(“看看這個報錯”)和 Claude 當時對圖的文字解讀(“截圖顯示了 404 錯誤…")都原樣保留。對話語義延續,你失去的只是"回翻檢視圖片本身"的能力。
實現這個邏輯的現成工具是 ianbmacdonald/claude-session-rescue。核心是一個純 Python 指令碼,原子寫入 + 自動 .bak 備份:
git clone https://github.com/ianbmacdonald/claude-session-rescue ~/tools/claude-session-rescue
# Dry-run 看會改什麼
python3 ~/tools/claude-session-rescue/scripts/session_rescue.py \
--session-id abc12345 --dry-run
# 正式執行
python3 ~/tools/claude-session-rescue/scripts/session_rescue.py \
--session-id abc12345
跑完你回 Claude Code 繼續發訊息就能走通了。
我踩到的兩個實際痛點
用上面的基礎指令碼修掉第一次之後,我又踩到兩個新問題:
痛點 1:Paseo 裡我不知道 tab 對應哪個 sessionId
我習慣在 Paseo 裡給 tab 起有意義的名字(按專案域劃分),但救援指令碼需要 session ID 前 8 位作為引數。我得先去 ~/.paseo/agents/<project>/*.json 裡翻找對應 agent 的 persistence.sessionId——每次都這樣挺煩。
解法:寫個包裝指令碼,自動按 tab 名查 sessionId。
痛點 2:問題會復發,需要定時預防
救援本身是"事後補救”——你已經撞到錯誤才去跑。但隨著使用量增加,會話裡積累的截圖越來越多,第二天可能又掛。最好是每天自動跑一次,而且要有安全閥,不能在我正在聊的時候把 JSONL 抽走。
需要的安全閥:
- 跳過活躍 session:如果某個 session 對應的
claude程序正在跑,跳過——避免寫衝突。 - 跳過剛寫入的:JSONL 在最近 N 分鐘內被改過 → 使用者可能正在聊,跳過。
- 圖片數閾值:圖片少於 N 張的 session 不清——保留近期視覺上下文。
- 備份輪轉:每次跑都會多一份
.bak,長期下來會累積。只保留最近 K 份。
工具化
我自己整理了一套指令碼:核心引用上游 ianbmacdonald/claude-session-rescue 處理 JSONL 剝圖,外面再包一層 Paseo 友好的手動救援 + 定時版 + 4 道安全閥。下面的程式碼片段你可以直接拿走拼裝。
scripts/paseo_rescue.sh — Paseo 友好的手動救援
# 列出所有命名 tab 和圖片數
bash paseo_rescue.sh
# 預覽
bash paseo_rescue.sh MyTabName --dry-run
# 正式救援
bash paseo_rescue.sh MyTabName
# 批次
bash paseo_rescue.sh --all
指令碼解析 ~/.paseo/agents/<project>/*.json 裡的 title 欄位和 persistence.sessionId,自動對映。使用前改指令碼頂部的 PASEO_AGENTS_DIR 變數指到你的專案 slug 就行。
scripts/paseo_rescue_auto.sh — 每日定時版 + 4 道安全閥
核心程式碼片段:
while IFS='|' read -r name sid cwd; do
jsonl="$CLAUDE_PROJECTS/${cwd_enc}/${sid}.jsonl"
# Valve 1: 活躍 claude 程序
if pgrep -f "claude.*${sid:0:8}" >/dev/null; then
log "[$name] skip: active process"
continue
fi
# Valve 2: 最近 30 分鐘內修改過
mtime=$(stat -f%m "$jsonl")
if [ $(($(date +%s) - mtime)) -lt 1800 ]; then
log "[$name] skip: recent write"
continue
fi
# Valve 3: 圖片數閾值
img_count=$(grep -o '"type":"image"' "$jsonl" | wc -l)
if [ "$img_count" -lt 5 ]; then
log "[$name] skip: only $img_count images"
continue
fi
# 清理 + 記錄
python3 "$RESCUE_SCRIPT" --session-id "${sid:0:8}"
# Valve 4: .bak 輪轉
ls -1t "${sid}.jsonl.bak"* | tail -n +4 | xargs rm -f
done < <(list_agents)
配合 macOS LaunchAgent / Linux systemd timer(examples 目錄裡有現成模板),每天本地時間 18:30 跑一次。有清理動作時 Telegram 推送摘要,空跑不通知。
監控納管
我本地的監控系統(另一個話題)會把這個定時任務納入統一的"備份任務"頁面:
- 任務狀態(綠/黃/紅)
- 上次成功時間、下次執行時間
- 清理的 session 數、釋放的空間、處理的圖片數
- 失敗自動 Telegram 告警
這是用我自己的監控框架整合的,repo 裡沒包含(避免繫結特定架構),但你可以參考 paseo_rescue_auto.sh 的日誌格式自己接入你的監控。
實用建議(預防 > 救援)
最好的救援是根本不需要救援:
- 貼截圖前先縮到 ≤ 1920 px 寬。macOS 可以
sips -Z 1920 file.png,或用 Shottr / CleanShot 等預設 1x 輸出的第三方工具。 - 長會話裡節制貼圖,能用文字描述就別貼圖。
- 對高強度使用者(每天貼 10+ 張截圖),開個每日定時清理,設
--min-images 5左右。 - 對運維/研究場景,記得把重要結論讓 Claude 文字化總結後再清理——圖沒了但文字記憶還在。
關於 API 規則的題外話
Anthropic 這個多圖規則我沒在官方文件的顯眼位置見過,實際踩到才反推出來。這種"規則觸發後回溯檢查歷史"的設計對客戶端不太友好——使用者感知是"我明明只貼了一張小圖怎麼就掛了"。如果 Claude Code 能在 API 返回這個錯誤時自動提示"是第 N 條訊息裡那張圖超限",體驗會好很多。
不過既然規則擺在那,我們能做的就是把救援鏈路做順滑。這套工具對我來說讓這個 bug 從"每次都要手忙腳亂"變成"18:30 自動處理,我一般都感知不到"。
連結
- 上游核心:https://github.com/ianbmacdonald/claude-session-rescue(JSONL 剝圖演算法,本文 wrapper 全部依賴它)
如果對你有用,在 X @panshi8848 反饋使用中遇到的問題。
📷 封面圖 · Flux Schnell AI 生成 · panshi.io 品牌風格