SlackBridge: Slack links <url|label> arrive as broken text "url|label" (no link, no preview)
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 25/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Stale
- Tech stack
- typescript
- Domain
- backend
Research direction
Read apps/meteor/server/bridges/slack/RocketAdapter.ts, especially convertSlackMsgTxtToRocketTxtFormat around line 529, and compare its link handling with apps/meteor/server/lib/import/slack/SlackImporter.ts around lines 692–693. Check the existing bridge tests for this conversion, then verify that labeled Slack links render with the intended target and URL previews. An open linked pull request (#43590) already addresses this issue.
Written by the indexing model from the issue text.
Description
Description:
SlackBridge does not convert Slack's link markup <url|label>. It only strips the angle brackets, so every link with a label arrives in Rocket.Chat as the literal text url|label. The message parser then treats the whole url|label string as one URL, so the link points to a wrong address and no URL preview is fetched.
Slack sends almost every link this way. Pasted links are usually <https://x.com/user/status/123|x.com/user/status/123>, and links with custom text are <https://example.com|some text>. On our workspace, where most messages come through SlackBridge, this affected about 15,000 bridged messages.
Steps to reproduce:
- Set up SlackBridge between a Slack workspace and Rocket.Chat.
- In a bridged Slack channel, post a link, e.g.
https://x.com/user/status/123, or a link with custom text. - Look at the bridged message in Rocket.Chat.
Expected behavior:
<https://x.com/user/status/123|x.com/user/status/123>becomeshttps://x.com/user/status/123: a clickable link that gets a preview.<https://example.com|some text>becomes[some text](https://example.com).
Actual behavior:
The message text is https://x.com/user/status/123|x.com/user/status/123. The rendered link target is that whole string, and the message's urls contains it too, so the OEmbed lookup fails and no preview is shown.
Cause:
convertSlackMsgTxtToRocketTxtFormat in apps/meteor/server/bridges/slack/RocketAdapter.ts handles links with a single replace that keeps the |label part:
slackMsgTxt = slackMsgTxt.replace(/<(http[s]?:[^>]*)>/g, '$1');
The Slack importer already handles the same markup correctly:
message = message.replace(/<(http[s]?:[^>|]*)>/g, '$1');
message = message.replace(/<(http[s]?:[^|]*)\|([^>]*)>/g, '[$2]($1)');
Using the importer's two replacements in the bridge would fix the broken links. Two details from patching this locally:
- When the label is just the URL itself (Slack's usual case: the URL without scheme, or a shortened form with
…), emitting the bare URL is better than[label](url). The parser autolinks a URL-looking label inside the markdown link, and the bare form keeps previews working. - The link replacement runs after
>is decoded (line 522), so a label containing>gets cut at that character. Converting links before the HTML entity decode avoids this.
Server Setup Information:
- Version of Rocket.Chat Server: 8.9.1 (the same code is on
developat 7625d7c and in 9.0.0-rc.8) - License Type: Community
- Number of Users: 38
- Operating System: Linux (Ubuntu, kernel 6.8)
- Deployment Method: docker
- Number of Running Instances: 1
- DB Replicaset Oplog: enabled (single-node replica set)
- NodeJS Version: 24.22.1
- MongoDB Version: 8.2.3
Client Setup Information
- Desktop App or Browser Version: any (the stored message text is wrong, so it does not depend on the client)
- Operating System: any
Additional context
We are running a locally patched image with this fix for now. I can open a PR if that would help.
Relevant logs:
No errors are logged; the conversion succeeds but produces the wrong text.
- Dominant language
- TypeScript
- Stars
- 46.5k
- Forks
- 14.1k
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 381
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing 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.
More from RocketChat/Rocket.Chat
-
Mark the empty state busy while a new search loads, like the table */}Possibly taken @aditya25bcy10173-a11y claimed this 2 days ago. Opentodo type: feature
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
RocketChat/Rocket.Chat#43699 · 1 comment · 1 reaction ·
Maintainers usually reply within 1 day
-
Timestamp with a time but no timezone shows as 1 January 1970Possibly taken @Sarthak-agrawal-tech claimed this 4 days ago. Opentype: bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
RocketChat/Rocket.Chat#43637 · 6 comments ·
Maintainers usually reply within 1 day
-
Move this mapping from useQuery's old `select` into a usePaginatedQuery `combine`Possibly taken @aditya25bcy10173-a11y claimed this 3 days ago. Opentodo type: feature
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
RocketChat/Rocket.Chat#43609 · 4 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
evaluate switching to the other tab when the selected tab's permission is revoked mid-sessionPossibly taken @schizophrenicmaniac claimed this 4 days ago. Opentodo type: feature
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
RocketChat/Rocket.Chat#43579 · 3 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
Docs say packages can be installed with `npm` but use unsupported `patch:` URLPossibly taken A pull request linked to this issue is open or already merged. Opentype: bug
Difficulty 1/5 1-3 hours Newbie friendliness 72/100
RocketChat/Rocket.Chat#43554 · 4 comments ·
Maintainers usually reply within 1 day
All issues in RocketChat/Rocket.Chat
Similar issues
-
bug
Difficulty 2/5 Half a day Newbie friendliness 68/100
amosblomqvist/learnharness#758 ·
Maintainers usually reply within 2 days
-
Change WorkspacesOpen
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
bitfocus/companion-module-renewedvision-propresenter-api#134 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
rcpch/digital-growth-charts-react-component-library#304 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
dsh-market/dsh-market#1210 · 1 comment ·
Maintainers usually reply within 1 day
-
good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
trustjonathan/STUDY-HUB#13 ·