claude-code - 💡(How to fix) Fix [BUG] Ctrl+V image paste fails for images >2000px since v2.1.98 — bundled sharp resize error silently swallowed [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#47063Fetched 2026-04-13 05:42:28
View on GitHub
Comments
2
Participants
2
Timeline
7
Reactions
0
Author
Timeline (top)
labeled ×5commented ×2

Since v2.1.98, pasting clipboard images with dimensions exceeding 2000px via Ctrl+V silently fails with "No image found in clipboard." Images ≤ 2000px paste normally. This is a regression — v2.1.97 handles all image sizes correctly.

Error Message

  1. Error caught by catch { return null } → caller shows "No image found"
  2. Show a meaningful error message instead of "No image found in clipboard"

Error Messages/Logs

(No error is logged — the exception is silently caught with catch { return null })

Root Cause

Root Cause Analysis

Fix Action

Fix / Workaround

  1. Copy any image with dimensions > 2000px to clipboard (e.g., a full-screen screenshot on a Retina display)
  2. Open Claude Code v2.1.98+
  3. Press Ctrl+V
  4. Expected: Image is pasted into the conversation
  5. Actual: Toast notification "No image found in clipboard"
  6. Workaround: Resize the image to ≤ 2000px before copying, then Ctrl+V works

Code Example

// v2.1.97 — 3 arguments, no external limits parameter
let A = await eo(Y, Y.length, "png");

---

// v2.1.98+ — 4 arguments, passes {maxWidth:2000, maxHeight:2000} limits
let O = await Sa(A, A.length, "png", q);

---

// After reading the file, before calling sa():
if (process.platform === "darwin" && buf[0] === 0x89 && buf[1] === 0x50) {
  let w = buf.readUInt32BE(16), h = buf.readUInt32BE(20);
  if (w > maxWidth || h > maxHeight) {
    await exec(`sips --resampleWidth ${maxWidth} "${screenshotPath}"`);
    buf = fs.readFileSync(screenshotPath);
  }
}

---

// Current: throws when dimensions > limit AND sharp fails
if (base64Size <= maxBase64Size && !overDimensionLimit)
  return { buffer: original, mediaType };

// Proposed: also fall back when dimensions > limit but base64 is small enough
if (base64Size <= maxBase64Size)
  return { buffer: original, mediaType };

---

No image found in clipboard. Use ctrl+v to paste images.
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Summary

Since v2.1.98, pasting clipboard images with dimensions exceeding 2000px via Ctrl+V silently fails with "No image found in clipboard." Images ≤ 2000px paste normally. This is a regression — v2.1.97 handles all image sizes correctly.

Environment

  • Claude Code: 2.1.98+ (tested on 2.1.104, confirmed working on 2.1.97)
  • macOS: 15.x (Darwin 25.3.0), Apple Silicon
  • Terminal: iTerm2 3.4.15
  • Node.js: v20.20.1

Root Cause Analysis

What changed in v2.1.98

The clipboard image processing pipeline was changed. In v2.1.97, the clipboard handler calls:

// v2.1.97 — 3 arguments, no external limits parameter
let A = await eo(Y, Y.length, "png");

In v2.1.98+, it was changed to:

// v2.1.98+ — 4 arguments, passes {maxWidth:2000, maxHeight:2000} limits
let O = await Sa(A, A.length, "png", q);

Why it fails

The sa() function (minified name varies by version) processes images through this flow:

  1. Calls sharp(buffer).metadata() to get dimensions — works fine
  2. If dimensions ≤ 2000x2000 → returns image as-is — works fine
  3. If dimensions > 2000x2000 → calls sharp(buffer).resize(...).toBuffer()FAILS
  4. Error caught by catch { return null } → caller shows "No image found"

The bundled sharp JS wrapper in cli.js cannot successfully perform the resize().toBuffer() operation. The native module (@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node v0.34.5) loads correctly, and a standalone sharp installation can resize the same image without issues. The failure is specific to the bundled sharp code within cli.js.

Verification

TestResult
osascript -e 'the clipboard as «class PNGf»'✅ Works (exit code 0)
osascript save to file✅ Works (writes valid PNG)
Node.js spawn with maxBuffer: 100MB✅ Works
Standalone sharp(buf).resize(2000, 904).toBuffer()✅ Works
Bundled sharp resize in cli.js❌ Fails silently
Paste image ≤ 2000px (no resize needed)✅ Works
Paste image > 2000px (resize triggered)❌ Fails

Confirmed version bisect

VersionmaxWidth/maxHeight limitsClipboard calls sa() with limitsStatus
2.1.97 (2026-04-08)Global vars TQ=2000, VQ=2000eo(buf, len, "png") — 3 args✅ Works
2.1.98 (2026-04-09)maxWidth:2000, maxHeight:2000Sa(buf, len, "png", limits) — 4 args❌ Broken
2.1.100SameRa(buf, len, "png", limits)❌ Broken
2.1.104Samesa(buf, len, "png", limits)❌ Broken

What Should Happen?

Images larger than 2000px should either:

  1. Be resized successfully using sharp before sending, OR
  2. Fall back to sending the original image if resize fails (the base64 size is often well within the 5MB API limit), OR
  3. Show a meaningful error message instead of "No image found in clipboard"

Steps to Reproduce

  1. Copy any image with dimensions > 2000px to clipboard (e.g., a full-screen screenshot on a Retina display)
  2. Open Claude Code v2.1.98+
  3. Press Ctrl+V
  4. Expected: Image is pasted into the conversation
  5. Actual: Toast notification "No image found in clipboard"
  6. Workaround: Resize the image to ≤ 2000px before copying, then Ctrl+V works

Proposed Fixes

Fix 1 (Recommended): Pre-resize with sips on macOS before passing to sa():

// After reading the file, before calling sa():
if (process.platform === "darwin" && buf[0] === 0x89 && buf[1] === 0x50) {
  let w = buf.readUInt32BE(16), h = buf.readUInt32BE(20);
  if (w > maxWidth || h > maxHeight) {
    await exec(`sips --resampleWidth ${maxWidth} "${screenshotPath}"`);
    buf = fs.readFileSync(screenshotPath);
  }
}

Fix 2: Fix the bundled sharp so resize().toBuffer() works correctly in the bundle environment.

Fix 3: In the sa() catch block, fall back to returning the original image when base64 size is within the API limit, even if dimensions exceed the pixel limit:

// Current: throws when dimensions > limit AND sharp fails
if (base64Size <= maxBase64Size && !overDimensionLimit)
  return { buffer: original, mediaType };

// Proposed: also fall back when dimensions > limit but base64 is small enough
if (base64Size <= maxBase64Size)
  return { buffer: original, mediaType };

Error Messages/Logs

No image found in clipboard. Use ctrl+v to paste images.

(No error is logged — the exception is silently caught with catch { return null })

Is this a regression?

Yes, this worked in v2.1.97

Last Working Version

2.1.97

Claude Code Version

2.1.104

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

Note: This is a different issue from #29776 (ENOBUFS / sandbox-exec). That issue affects ALL images regardless of size. This issue specifically affects only images > 2000px because it triggers the sharp resize code path which fails in the bundled environment.

extent analysis

TL;DR

The most likely fix is to pre-resize images larger than 2000px using sips on macOS before passing them to the sa() function.

Guidance

  • Verify that the issue is indeed caused by the sharp resize operation failing in the bundled environment by checking the sa() function's behavior with different image sizes.
  • Consider implementing Fix 1 (pre-resizing with sips) as a temporary workaround until the bundled sharp issue is resolved.
  • If Fix 1 is not feasible, explore Fix 3 (falling back to the original image when base64 size is within the API limit) as an alternative.
  • To further diagnose the issue, add logging or error handling to the sa() function to understand why the resize().toBuffer() operation is failing.

Example

// Example of pre-resizing with sips
if (process.platform === "darwin" && buf[0] === 0x89 && buf[1] === 0x50) {
  let w = buf.readUInt32BE(16), h = buf.readUInt32BE(20);
  if (w > maxWidth || h > maxHeight) {
    await exec(`sips --resampleWidth ${maxWidth} "${screenshotPath}"`);
    buf = fs.readFileSync(screenshotPath);
  }
}

Notes

The issue is specific to the bundled sharp code within cli.js and does not affect standalone sharp installations. The proposed fixes aim to mitigate the issue until the underlying problem with the bundled sharp is resolved.

Recommendation

Apply Fix 1 (pre-resizing with sips) as a temporary workaround, as it is a relatively simple and effective solution that can be implemented quickly.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] Ctrl+V image paste fails for images >2000px since v2.1.98 — bundled sharp resize error silently swallowed [2 comments, 2 participants]