Skip to content

Keep Mastodon auto-refresh under the rate limit so posts don't fail with 429 - #24

Merged
masonasons merged 2 commits into
masonasons:mainfrom
Orinks:fix/rate-limit-auto-refresh
Sep 24, 2026
Merged

masonasons merged 2 commits into
masonasons:mainfrom
Orinks:fix/rate-limit-auto-refresh

Conversation

@Orinks

@Orinks Orinks commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Keeps Mastodon auto-refresh within the server's rate limit so posting stops failing with 429. There are two changes: auto-refresh backs off when the limit is nearly spent, and idle threads and user timelines are polled every 15 minutes instead of every minute.

Problem

On Mastodon, posting fails with the error earcon and nothing in the log. After adding logging, the server response turned out to be:

POST https://<instance>/api/v1/statuses failed: status=429 body={"error":"Too many requests"}

Auto-refresh (default every 60s) refreshes every open timeline. With 57 timelines restored (mostly user and thread timelines, about 2 requests each), that's roughly 110 requests a minute. Mastodon allows about 300 per 5 minutes per account, so the budget is gone within about 3 minutes of each window, and anything the user does after that gets a 429 until the window resets. Posting works right after launch and then starts failing.

Fix

  • MastodonAccount routes every HTTP call through a single send() helper that reads X-RateLimit-Remaining / X-RateLimit-Reset from the user's own instance. Remote-instance timelines are ignored.
  • When fewer than 100 calls remain, or on a 429, background_refresh_allowed() returns false until the server's reset time. If there's no reset header, it waits 5 minutes.
  • CoreSession::refresh_all_accounts() (the auto-refresh tick) skips accounts that are throttled. Manual refresh, streaming and user actions are unaffected. Bluesky keeps the default of true.
  • Thread and user timelines whose newest post is more than a day old are auto-refreshed only every 15th tick (every 15 minutes at the default interval) instead of every tick. The timeline being viewed always refreshes, and manual refresh is unchanged. Most of the budget went to these idle tabs. No setting and no UI, so every front end gets it.
  • Failed non-GET Mastodon requests are now logged with their status and the first 300 bytes of the body. WinHTTP send/receive failures include the GetLastError() code. Without this, the 429 couldn't be seen.

Testing

  • build.bat test: 822 checks, 0 failures. The new test_mastodon_rate_limit_pauses_refresh covers plenty of budget, nearly spent, reset time already passed, and a bare 429.
  • Live: the 429 was reproduced and captured with the logging in this PR on a real account with 57 open timelines. The back-off itself still needs a longer live run.

🤖 Generated with Claude Code

Orinks and others added 2 commits September 24, 2026 09:09
Auto-refresh polls every open timeline each interval. With many timelines
open (57 here, ~110 requests/minute) that exhausts Mastodon's ~300 calls
per 5 minutes per account within minutes, and posts then fail with 429
and only an error earcon.

Route every MastodonAccount HTTP call through one send() helper that reads
X-RateLimit-Remaining/Reset from our own instance; when fewer than 100
calls remain (or on a 429), background refresh is skipped for that account
until the server's reset time. Also log failed non-GET requests with their
status and error body, and include the WinHTTP error code on transport
failures, so a failed action leaves something in the log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thread and user timelines whose newest post is over a day old rarely
change, but with dozens open, refreshing each every auto-refresh tick is
what spends the rate limit. Refresh those only every 15th tick; the
timeline being viewed always refreshes, and manual refresh is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Orinks Orinks changed the title Pause Mastodon auto-refresh when the rate limit runs low Keep Mastodon auto-refresh under the rate limit so posts don't fail with 429 Sep 24, 2026
@masonasons

Copy link
Copy Markdown
Owner

I'll merge this, but mate, I very strongly suggest you use lists. having 60 user timelines open is going to put strain on your Mastodon server regardless. That's just, wow.

@masonasons
masonasons merged commit 7437337 into masonasons:main Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants