Skip to content

fix: prevent Ctrl+V crash when clipboard contains non-text data#1758

Open
exqqstar wants to merge 2 commits intoMoonshotAI:mainfrom
exqqstar:fix/clipboard-crash-non-text-paste
Open

fix: prevent Ctrl+V crash when clipboard contains non-text data#1758
exqqstar wants to merge 2 commits intoMoonshotAI:mainfrom
exqqstar:fix/clipboard-crash-non-text-paste

Conversation

@exqqstar
Copy link
Copy Markdown

@exqqstar exqqstar commented Apr 4, 2026

Related Issue

Resolve #1757
Related to #1750

Description

Two-layer fix for TypeError crash when pressing Ctrl+V with non-text clipboard content (e.g. a screenshot on a model
that doesn't support image input, or any payload where pyperclip.paste() returns None).

Layer 1: _SafePyperclipClipboard

Wraps PyperclipClipboard.get_data() to catch TypeError and treat None/non-string payloads as empty text
(ClipboardData()). This protects all clipboard access paths in prompt_toolkit — not just our explicit Ctrl+V
handler, but also built-in paste operations (Ctrl+Y, Vi p, etc.).

Layer 2: _try_paste_media() return value

When images are detected in the clipboard but the current model does not support image_in, the paste event is now
consumed (return True) instead of returning False and falling through to the text paste path. The "Image input is
not supported" warning is still printed.

What's NOT changed

  • Models that support image input (e.g. kimi-k2.5) — behavior unchanged.
  • _try_paste_media() still returns False when image caching fails — existing fallback semantics preserved.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked the related issue, if any.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have run make gen-changelog to update the changelog.
  • I have run make gen-docs to update the user documentation.

Open with Devin

Two-layer fix for TypeError crash on paste:

1. _SafePyperclipClipboard: wraps PyperclipClipboard.get_data() to treat
   None/non-string payloads as empty text, protecting all clipboard access
   paths in prompt_toolkit (not just our Ctrl+V handler). Covers MoonshotAI#1750.

2. _try_paste_media() return value: when images are detected but the model
   does not support image_in, the paste event is now consumed (return True)
   instead of falling through to the text paste path.
Copilot AI review requested due to automatic review settings April 4, 2026 16:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents a TypeError crash when pasting from the clipboard (Ctrl+V and other prompt_toolkit paste paths) if the clipboard contains non-text data (e.g., screenshots), and ensures unsupported image paste events are consumed instead of falling through to text paste.

Changes:

  • Introduces _SafePyperclipClipboard to treat None/non-string clipboard payloads as empty text.
  • Updates _try_paste_media() to consume paste events when images are detected but the current model lacks image_in.
  • Adds/updates tests covering the unsupported-image consumption behavior and None clipboard payload handling.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/kimi_cli/ui/shell/prompt.py Adds safe clipboard wrapper and adjusts media paste return semantics to avoid Ctrl+V crash/fallthrough.
tests/ui_and_conv/test_prompt_clipboard.py Updates image-unsupported test expectations and adds a regression test for pyperclip.paste() -> None.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1898 to 1902
if parts:
event.current_buffer.insert_text(" ".join(parts))
event.app.invalidate()
return bool(parts)
return bool(parts) or unsupported_images

Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_try_paste_media() now returns True even when no content is inserted (when images are detected but unsupported), but its docstring still says it returns True only if media content was inserted. Please update the docstring to reflect the new "paste was handled/consumed" semantics so callers/tests don’t rely on the old meaning.

Copilot uses AI. Check for mistakes.
data = super().get_data()
except TypeError as exc:
logger.debug(
"Ignoring non-text clipboard payload in text paste handler: {error}",
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The debug message in _SafePyperclipClipboard.get_data() says "in text paste handler", but this clipboard wrapper is used for all prompt_toolkit paste operations (Ctrl+V, Ctrl+Y, Vi p, etc.). Consider rewording the log message to be accurate (e.g., "clipboard get_data" / "paste") to avoid confusion when debugging.

Suggested change
"Ignoring non-text clipboard payload in text paste handler: {error}",
"Ignoring non-text clipboard payload in clipboard get_data: {error}",

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +205
@@ -199,9 +200,11 @@ def test_paste_image_unsupported_model(monkeypatch, capsys) -> None:

result = ps._try_paste_media(cast(KeyPressEvent, event))

# No image placeholder inserted, returns False so caller can fall back to text paste
assert result is False
# Media was recognized, so the paste event should be consumed even though the
# model cannot accept image input.
assert result is True
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

capsys is accepted by test_paste_image_unsupported_model_consumes_paste but not used. Either drop the fixture parameter or use it to assert the expected warning text is printed (this PR description calls out that the warning is still shown).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

- Update _try_paste_media() docstring to reflect "paste handled" semantics
- Fix misleading debug log message in _SafePyperclipClipboard
- Remove unused capsys fixture from test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ctrl+V crashes with TypeError when clipboard contains non-text data (e.g. screenshot)

2 participants