Skip to content

Instantly share code, notes, and snippets.

@nikclayton
Last active April 29, 2026 15:20
Show Gist options
  • Select an option

  • Save nikclayton/8030b9a3a22e1ef93ac401602386de08 to your computer and use it in GitHub Desktop.

Select an option

Save nikclayton/8030b9a3a22e1ef93ac401602386de08 to your computer and use it in GitHub Desktop.

Mention display bug

Problem/tl;dr:

Cause:

  • The mentions.url references for those accounts (when surfaced through the Mastodon API on mastodon.social) don't match the a.href attribute in the HTML content for the post
  • This causes clients to disregard the @-mention

Meta:

Bug 1

Here's the HTML that's returned for that post (the Status.content property).

<p><a href="https://mastodon.xyz/users/anca" rel="nofollow noopener" target="_blank">@anca@mastodon.xyz</a> I hope it's interesting! 😄</p>
<p>did an episode with <a href="https://social.logal.dev/users/logan" rel="nofollow noopener" target="_blank">@logan@social.logal.dev</a> for his Owncast bot ( <a href="https://git.logal.dev/LogalDeveloper/Owlbot/issues" rel="nofollow noopener" target="_blank">git.logal.dev/LogalDeveloper...</a> )</p>
<p>and</p>
<p><a href="https://mastodon.me.uk/users/Floppy" rel="nofollow noopener" target="_blank">@Floppy@mastodon.me.uk</a> for <a href="https://3dp.chat/users/manyfold" rel="nofollow noopener" target="_blank">@manyfold@3dp.chat</a> ( <a href="https://manyfold.app/" rel="nofollow noopener" target="_blank">manyfold.app/</a> ).</p>
<p>Coming up soon I hope to talk with <a href="https://mstdn.social/users/lefractal" rel="nofollow noopener" target="_blank">@lefractal@mstdn.social</a> and <a href="https://hachyderm.io/users/mapache" rel="nofollow noopener" target="_blank">@mapache@hachyderm.io</a> and <a href="https://mastodon.social/users/benpate" rel="nofollow noopener" target="_blank">@benpate@mastodon.social</a> .</p>
<p>You can follow <a href="https://freestreamers.btfree.org/federation/u/when" rel="nofollow noopener" target="_blank">@when@freestreamers.btfree.org</a> or the RSS or iCal at <a href="http://freestreamers.BTfree.org" rel="nofollow noopener" target="_blank">freestreamers.BTfree.org</a></p>
<p>Or <a href="https://worksonmymachine.live/federation/user/ozoned" rel="nofollow noopener" target="_blank">@ozoned@worksonmymachine.live</a></p>
<p>Or <a href="https://tubefree.org/accounts/ozoned" rel="nofollow noopener" target="_blank">@ozoned@tubefree.org</a></p>

Some of the @-mentions in that post aren't linked by Pachli, some of them are.

One that isn't is @anca@mastodon.xyz, one that is is @ozoned@worksonmymachine.live.

The relevant HTML for those two is:

... <a href="https://mastodon.xyz/users/anca" rel="nofollow noopener" target="_blank">@anca@mastodon.xyz</a> ...

and

... <a href="https://worksonmymachine.live/federation/user/ozoned" rel="nofollow noopener" target="_blank">@ozoned@worksonmymachine.live</a> ...

There are some relevant bits of the Mastodon API documentation to look at.

Mentions and hashtags are tags. Custom emojis remain in their plain text shortcode form. To give those entities their semantic meaning and add special handling, such as opening a mentioned profile within your app instead of as a web page, metadata is included with the Status, which can be matched to a particular tag.

-- https://docs.joinmastodon.org/api/guidelines/#tags

That takes us to:

Status.mentions

  • Description: Mentions of users within the status content.
  • Type: Array of Status::Mention

-- https://docs.joinmastodon.org/entities/Status/#mentions

Which takes us to:

Status::Mention attributes ...

  • url
    • Description: The location of the mentioned user’s profile. ...

-- https://docs.joinmastodon.org/entities/Status/#Mention

So, when Pachli is parsing the text to figure out if it's a mention it loops over all the links in the post, and for each one it checks to see if there is an entry in the Status.mentions array with a url property that matches the link's href attribute.

The mastodon.social API link for the post is https://mastodon.social/api/v1/statuses/116485595793382258. If I fetch that, pretty-print the JSON, and excerpt the relevant bits from the mentions array I see this:

  "mentions": [
    // ...
    {
      "id": "48650",
      "username": "anca",
      "url": "https://mastodon.xyz/@anca",
      "acct": "anca@mastodon.xyz"
    },
    // ...
    {
      "id": "116210642677532687",
      "username": "ozoned",
      "url": "https://worksonmymachine.live/federation/user/ozoned",
      "acct": "ozoned@worksonmymachine.live"
    }
  ],

Going back to the original HTML, the a.href attribute for @anca was https://mastodon.xyz/users/anca. But in the entry in the mentions array the url property is https://mastodon.xyz/@anca.

They're not the same, so Pachli doesn't consider this to be match.

For the @ozoned@... account a.href is https://worksonmymachine.live/federation/user/ozoned and the entry in mentions is also https://worksonmymachine.live/federation/user/ozoned.

They are the same, so Pachli considers this to be a matching mention.

If I had to guess, I don't think mastodon.social is changing the mentions data it gets from btfree.social, which is why I suspect the original data sent from the Bonfire server is incorrect, and the problem will need to be fixed there.

Bug 2

If Pachli checks to see if a link that looks like a mention is in the Status.mentions array, and it can't find a match, the link is removed.

That's why you're seeing some of these as plain text instead of links.

That's a Pachli bug -- if the link can't be resolved to an account (or a hashtag) it should be left as a regular link.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment