pingdotgg / pingdotgg/t3code

Pasting markdown with inline code inside bold, italic or strikethrough silently does nothing

Open
#12,247 2 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accepted bug via-triage
Dominant language
TypeScript
Stars
23k
Forks
5.9k
Avg merge
11h 14m
Merged PRs (30d)
357

Description

What happened

Pasting into the desktop chat composer silently does nothing — no text appears, no error, no toast. It reproduces with any markdown containing inline code wrapped in bold, such as an assistant response full of **`path/to/File.cs`** headings. Other pastes into the same composer work, which initially made it look like a size limit.

Diagnosis

The composer's paste handler calls event.preventDefault() before it inserts anything (apps/web/src/components/ComposerPromptEditorTiptap.tsx:948), so any failure in the insert step swallows the paste with no feedback.

The insert step builds Tiptap JSON via buildTiptapContent (apps/web/src/composer-rich-text-doc.ts:166). When inline code sits inside bold, italic or strikethrough, parseInlineMarkdown nests the marks and the builder emits a text node carrying both, e.g. marks: [{type:"bold"},{type:"code"}].

That is an invalid mark set. @tiptap/extension-code@3.31.3 declares excludes: "_", so the code mark cannot coexist with any other mark. ProseMirror rejects the node instead of inserting it, and because preventDefault() already ran, the paste is lost silently.

Disabling the rich text composer makes the same paste succeed, which confirms the mechanism: plain mode passes styling: false, so parseInlineMarkdown never runs and no marks are emitted.

Size and line count are not factors. An 8 KB single line and a 110-block multi-line paste both insert fine as long as no mark set combines code with another mark.

Suggested direction (not a patch): have buildTiptapContent avoid emitting code alongside other marks — either drop the sibling marks on a code span, or leave the surrounding markers literal, matching the "unmatched markers stay literal" rule already stated in composer-rich-text.ts:10.

Steps to reproduce
  1. Open the desktop app with a local server and focus the chat composer, with the rich text composer enabled (the default).
  2. Copy this exact 8-character string to the clipboard: **`x`**
  3. Paste into the composer.

Nothing is inserted. Disabling the rich text composer and repeating step 3 inserts the text correctly.

Controls that all paste correctly, confirming the trigger is the mark combination and not size or line count:

Pasted Marks produced Result
https://github.com/pingdotgg/t3code none inserts
alpha + newline + bravo none inserts
single line, 8,000 chars none inserts
alpha **bold** bravo bold inserts
`x` code inserts
**`x`** bold+code nothing inserted

*`x`* and ~~`x`~~ produce italic+code and strike+code and are expected to fail identically.

Version

0.0.43-nightly.20260917.1851 (tag v0.0.43-nightly.20260917.1851, commit 0150c6a5)

Environment

macOS (darwin arm64 27.0.0), Node v26.8.2, launched as npx t3@nightly, desktop app against a local server on 127.0.0.1:3773, composerRichTextEnabled at its default of true

Evidence
Mark sets emitted by buildTiptapContent() for the user's 6,483-byte payload
(run against the pure builder at tag v0.0.43-nightly.20260917.1851):

  code           x 43
  bold+code      x  8   <-- invalid; `code` declares excludes: "_"
  bold           x  6
  italic         x  1

Minimal cases:
  "**bold**"     marks=[bold]
  "`code`"       marks=[code]
  "**`x`**"      marks=[bold+code]     <-- nothing inserted
  "~~`x`~~"      marks=[strike+code]
  "*`x`*"        marks=[italic+code]

@tiptap/extension-code@3.31.3/dist/index.js:
  54: name: "code",
  58: excludes: "_",
  59: code: true,
(unpatched in this build; patches/ contains no @tiptap entry)

~/.t3/userdata/logs/server.trace.ndjson   — no failures around the paste
~/.t3/userdata/logs/desktop.trace.ndjson  — all spans exit Success; renderer-side
                                            exceptions are not captured here, which
                                            is why this failure left no trace at all
Related issues

#8331 (pasting code containing @ creates invalid mentions) touches the same paste path but fails in the mention tokenizer, not the mark schema. #5626 (composer lag with large input) is a performance issue, not a silent drop. Neither is a duplicate.

Fix applied or workaround

Nothing was written to the machine. Verified workaround: disabling the rich text composer setting makes the paste succeed. Also available: save the text as a .txt file and attach it, or rely on pastes ≥32 KiB auto-folding into a pasted-text.txt attachment (packages/client-runtime/src/textPaste.ts:1), which bypasses the inline insert entirely.

Filed by

Claude Code (claude-opus-5) via t3 triage

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at apps/web/src/composer-rich-text-doc.ts:166 and trace buildTiptapContent through parseInlineMarkdown, then inspect the paste handler at apps/web/src/components/ComposerPromptEditorTiptap.tsx:948. Reproduce with x, x, and x in the rich text composer. Done means these pastes insert content without invalid code-plus-other-mark combinations, while unmatched markers remain literal as described in composer-rich-text.ts:10.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.