Why Does a GitHub Stale Bot Close Feature Requests People Still Want?
A stale bot closes an issue because nobody left a new comment on it inside a fixed window, and that's the entire check. GitHub's own actions/stale marks an issue stale after 60 days with no update to its updated_at field, then closes it 7 days after that if still nothing changes. Reactions don't reset that clock. The action's documentation never mentions thumbs-up counts, view counts, or how many other issues raise the same request. The only inputs it reads are comments, edits, labels, milestones, and assignees. A feature request with forty 👍 reactions and zero new comments in ten weeks looks, to the bot, indistinguishable from an issue nobody has thought about since the day it was filed.
That's the mechanical answer. The reason it feels wrong is that "still wanted" and "recently commented on" are different things, and the bot only measures the second one. An issue can be exactly as wanted on day 67 as it was on day 1. The people who want it aren't obligated to keep typing "+1" to prove it, and if they do, that comment resets the timer, so the cycle just repeats two months later.
What the default actually checks, and what it ignores
The two defaults worth knowing are days-before-stale: 60 and days-before-close: 7, per the action's README. Inside that window, the only way to stop the clock is a genuine update to the issue, a new comment, an edit, a label change, a milestone, or an assignee. The README's exemption options are exempt-issue-labels, exempt-milestones, and exempt-assignees; there is no exempt-above-N-reactions or anything close to it. Reaction counts, duplicate-report counts, and cross-repo mentions sit entirely outside what the bot can see, by design. It's a lightweight action reading one field on one issue, not a demand-tracking system.
That gap is exactly what people keep filing issues about against the tool itself. An open issue on actions/stale describes the failure mode directly: "issues or pull requests where the reporter is waiting on the response or feedback from the maintainer are closed as 'stale'... this can be extremely frustrating for the user because they continuously waste their time (and clutter the comments) by keeping an issue 'updated', eventually giving up." A similar report on the older probot/stale puts the underlying complaint in one line: "just because the repository maintainer has not answered does not make the issue stale." Both are asking for the same thing the built-in exemptions don't offer, a way to say "this one still matters" that isn't a fresh comment.
The counter-argument, made at length in the widely shared post "GitHub stale bot considered harmful", is that treating an open issue as a problem to be cleaned up is the wrong frame to begin with. Drew DeVault argues an issue tracker doubles as "a place for motivated users to collaborate," not a queue of action items owed a response, and that "there is no shame in having a lot of open issues — if anything, it signals popularity." Whether or not a maintainer agrees with that framing for their own repo, it explains why so many teams end up disabling or heavily configuring the default stale workflow rather than running it as shipped.
Kiln's cache-path issue, closed twice
Kiln, an open-source build cache for Rust, has exactly one maintainer: Isla Moreno, who works on it evenings and weekends around a day job. In March, someone filed an issue asking for workspace-relative cache paths instead of absolute ones, so CI runners with different checkout locations could still share a cache. Isla replied that it was a reasonable idea and she'd get to it when she had a free weekend, then didn't, for two months.
actions/stale marked it stale on day 60 and closed it on day 67, exactly as configured. In the seven weeks between the last comment and closure, the issue picked up eleven 👍 reactions and two new duplicate filings from people who hadn't seen the original. None of that touched the countdown.
Second reporter, June: Is there a plan for relative cache paths? Just hit the same problem trying to share a cache across two CI containers.
Isla: Huh, that got closed on me a while back, didn't realize. Reopening, sorry. I'll actually look at this one.
She reopened it. It went stale again in August, on the same clock, because the fix still hadn't happened and nobody had commented in the meantime. Once she noticed the pattern, Isla's actual fix was simple. She added enhancement to her repo's exempt-issue-labels list so any issue she'd triaged and accepted stopped aging out automatically. That single config change fixed the specific issue. It didn't fix the fact that she only found out about the duplicate report because someone happened to mention it in a reply, and she still had no count of how many people had actually hit this beyond however many left a reaction or filed a copy.
The DIY fixes, and where they stop
Three adjustments cover most of what a small team needs, and they're worth doing regardless of anything past that point:
- Exempt anything triaged. Add
exempt-issue-labels: enhancement,accepted,help-wanted(or whatever your accepted-work label is) so the bot only ever ages out issues nobody has looked at, not issues waiting on the maintainer's own backlog. - Widen the window before adding it back at all. A
days-before-staleof 60 or 90 with a generousdays-before-closegives real feature requests more runway than the tool's own numbers assume you want. - Check reactions before the job runs. A short
actions/github-scriptstep that reads each issue's reaction count via the API and applies the exempt label above some threshold before the stale job executes will keep a heavily-upvoted request from closing on comment silence alone. It's a script you maintain, not a checkbox.
None of that gives you a count. Reactions and duplicate filings tell you a request has resurfaced, but turning "eleven thumbs-up and two duplicate issues" into "thirteen people, in three companies, want this" is manual work. It means reading each reaction's profile, matching duplicate issues by hand, and remembering to check again next month. It scales to one maintainer checking one repo occasionally. It doesn't scale to a team with issues arriving from GitHub, a support inbox, and a Slack channel at the same time, where the same request can be stale-closed on GitHub while it's still alive and active somewhere else the bot never looks.
That's the point where we'd point you at Modem. Modem watches connected GitHub repos alongside Slack, Discord, and support tools, and instead of measuring one issue's comment timestamp, it counts how many separate people and companies keep raising the same underlying request across all of them, closed issue or not. A request that GitHub's bot auto-closed for silence still shows up as an open, counted topic in Modem if people keep mentioning it elsewhere, with every mention linked back to who raised it. We build Modem, so weigh that against the alternatives. But the gap it closes is specific. A stale bot's silence isn't the same fact as nobody wanting the thing, and Modem is built to keep tracking the second fact even after GitHub has acted on the first.
If your repo's real problem is broader than one bot's defaults, duplicate reports piling up, or nobody able to say who actually asked for what, the wider mechanics are in how to triage GitHub issues at scale and can GitHub detect duplicate issues before they pile up.
What to change today
The default actions/stale config closes on silence alone, so the fastest fix is a config change, not a rewrite: label your own backlog as exempt and stop treating 60 days as sacred if that's not how fast your team actually replies. That stops the bot from punishing work you've already accepted. It still won't tell you when a closed issue is being asked for on Slack, Discord, or a support ticket, the exact channels the bot never reads. For that, someone has to be watching more than the one field the bot checks.
