Troubleshooting Mastodon Backfeed and Stale Webmentions
A practical runbook for common failure modes in Mastodon + Bridgy + webmention.io setups: token scopes, canonical URLs, delayed backfeed, and stale reactions that no longer exist upstream.
Category: Development
Automating syndication was the easy part. Getting reaction backfeed and cleanup right — so that likes, reposts, and replies from Mastodon appear on the canonical post and disappear when the source is deleted — needed considerably more care. This is the practical checklist that emerged from debugging real failures.
The setup
- Canonical site: Astro 6 static build at
adrian-altner.de. - Bridge: Bridgy Fed, mapping Mastodon interactions to canonical URLs via
u-syndication. - Store: webmention.io, queried at build and from the client for live updates.
Outside the authorized scopes
Problem: Mastodon returns:
{"error":"This action is outside the authorized scopes"}
The access token is missing required permissions.
Implementation: for script-based posting, issue a token with at least:
write:statuseswrite:media
Also strip unnecessary API calls that would need extra scopes. Removing a pre-flight verify_credentials from the post flow eliminated a class of scope failures that had nothing to do with posting.
Backfeed not appearing on Bridgy
Problem: a common trap — interacting with the syndicated Mastodon post before the site is redeployed with the matching u-syndication link. If Bridgy can’t map the social interaction back to the canonical page URL, it shows nothing.
Implementation: fix order matters.
- Deploy first so “Shared on Mastodon” is live on the page.
- Use Bridgy’s
Poll now/Crawl now. - If still missing, trigger
Resend for post. - Retry the interaction.
Solution: the u-syndication link has to exist on the canonical page at the moment Bridgy crawls. Any sequence that reverses that ends in silent data loss — the reactions happened, but Bridgy had nowhere to route them.
Canonical URL mismatch (trailing slash)
webmention.io target matching is exact. .../hello-world and .../hello-world/ are different targets.
When debugging, always test with the canonical URL as it appears on the page — including trailing slash — otherwise you can easily read an empty result and chase the wrong bug for an hour.
429 Too many requests on media uploads
Problem: large backfills saturate media API limits fast.
Implementation: the syndication script now retries media uploads with backoff and honours Retry-After when the server sends it. Status posting continues even if a media upload ultimately fails, so the text post goes out and backfill progress isn’t blocked by images.
Deleted likes/reposts still visible
The most annoying failure mode. Deletions don’t always propagate cleanly through every layer — webmention.io can still hold the old reaction record, and the source URL may still return HTTP 200 even when the interaction itself is gone upstream.
Implementation: source re-validation at interaction level, not just URL existence:
- Mastodon — validate
favorited-by/reblogged-byagainst the status’s interaction APIs. - Bluesky — validate
liked_by/reposted_byagainst the public API lists. - Replies — validate source post existence directly via the platform APIs.
Solution: if the upstream interaction or source post is gone, it’s filtered out automatically at render time — no manual dashboard surgery required.
Client refresh not removing stale UI
Problem: even with correct filtering server-side, the UI can stay stale if the client refresh only handles additions.
Implementation: the webmentions component now tracks the current count and re-renders on both directions:
- new mentions added
- existing mentions removed
Solution: deletions become visible without having to manually prune in the webmention.io dashboard.
A practical debugging order
When something looks wrong, this order cuts through the noise:
- Verify the canonical target URL — including trailing slash.
- Inspect filtered local endpoint output.
- Check source interaction / post existence upstream.
- Trigger Bridgy poll / crawl.
- Only then touch manual dashboard deletion.
Most “it still shows” issues are one of those five, not a rendering bug.
What to take away
- Token scopes are the first thing to check.
write:statusesandwrite:mediaare the minimum; cut any pre-flight calls that need more. - Deploy before interacting. Bridgy needs the
u-syndicationlink on the canonical page at crawl time, not later. - Trailing slashes are load-bearing. Treat them as part of the identifier everywhere — webmention.io, state files, component queries.
- Re-validate upstream interactions, not just URLs. A source URL can return 200 long after the like itself is gone — only the interaction API tells the truth.
- Client refresh must handle both directions. Additions and removals, otherwise deleted reactions linger in the UI forever.