Pasting markdown with inline code inside bold, italic or strikethrough silently does nothing
Nobody has claimed this yet.
- 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
- Open the desktop app with a local server and focus the chat composer, with the rich text composer enabled (the default).
- Copy this exact 8-character string to the clipboard:
**`x`** - 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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 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.x
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