|Josh Ghent

Why your Dependabot PRs aren't merging — and 4 fixes that actually work

dependabotci/cddependency managementgithubpull requests

Why your Dependabot PRs aren't merging — and 4 fixes that actually work

Open the PR list. Filter by author:app/dependabot. Sort by oldest.

47 PRs. The youngest is six weeks old. The oldest is from the previous fiscal year. Three of them are flagged as security-critical. Half have red CI. Two are from packages that don't exist on npm anymore because the maintainer renamed the org.

If that mental image just made you wince, this post is for you. I've run dev teams that lived in this state for too long, and I've spent the last year actually fixing it. Here's what's really going on, and the four things that move the needle.

Why PRs rot — the diagnosis

Dependabot itself isn't broken. The detection and PR-opening half of the job is fine. The problem is what happens — or doesn't — between "PR opened" and "PR merged." There are four failure modes, and almost every stuck PR is one of them.

1. CI failed on a type bump or breaking change

The bot bumps @types/react from 18 to 19. One file in your codebase uses a type that got narrowed. CI goes red on a TypeScript error. The fix is two lines. But the PR is from a bot, so no human is assigned, and the failure isn't Dependabot's fault — it's a real code change you'd need to make.

So the PR sits. The bump is technically correct. The build is technically broken. Nobody owns the gap.

2. Transitive dependency stuck behind a parent

Your scanner is screaming about lodash.template. You don't import it directly. Some ancient version of gulp-something does. The fix isn't bumping lodash.template — it's bumping the parent, which is a breaking change that touches your build pipeline.

Dependabot opens the PR for the transitive bump. It can't merge cleanly because the parent's lockfile entry overrides it. Or it can, but the parent's resolution rolls it back at the next install. Either way, the PR is theatre.

3. No clear owner, and merge anxiety

This is the quiet killer. The PR has no assignee. The "frontend" team thinks "platform" owns dependency hygiene. Platform thinks the team that owns the package.json owns it. Nobody schedules it. And the people who could merge it have a faint anxiety that this innocuous-looking bump might break production at 3am, so they leave it for "someone with more context." There is no someone with more context. The bot wrote it.

4. Volume — five PRs a week becomes fifty in a quarter

Even if every individual PR is mergeable in five minutes, five PRs a week across ten repos is 250 review-events per quarter. Nobody has 250 review-events of headspace spare. So you triage the obviously safe ones, ignore the rest, and the queue grows linearly while your attention doesn't.

This is the one teams underestimate most. Dependabot doesn't have a volume problem at one repo. It has one at twenty.

Fix 1: group updates so you review fewer PRs

The single highest-leverage change is grouping. Instead of one PR per package, you get one PR per logical group per week. Reviewing "all dev dependencies, weekly" is a fundamentally different cognitive load than reviewing eight individual PRs.

Drop this in .github/dependabot.yml:

version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    groups:
      dev-dependencies:
        dependency-type: "development"
      production-minor-patch:
        dependency-type: "production"
        update-types:
          - "minor"
          - "patch"
    open-pull-requests-limit: 10

Two groups: dev deps (review once a week, merge if green) and prod minor/patch (review with a bit more care, but still as a batch). Major prod bumps still come as individual PRs because they deserve individual scrutiny.

In my experience this alone cuts your open-PR count by 60–70%. It does not fix any of the other three failure modes. But it makes them visible instead of buried.

Fix 2: actually fix the CI failures

This is the one no off-the-shelf tool fully solves. When a Dependabot PR fails CI on a real-but-trivial code change, you have three options:

  1. A human fixes it.
  2. You skip it and accept the security risk.
  3. Something else fixes it.

Mergify and similar tools can auto-merge green PRs and rebase stale ones, which helps with drift. They don't read the failing test output and write a code change. So if the failure is a type narrowing, a snapshot update, or a renamed export, a human still has to step in.

This is the specific gap I built RepoWarden to close. When CI goes red on a dependency PR, it reads the failure, writes the fix, pushes a commit, re-runs CI, and tags the original CODEOWNER for review. Same end state as a tired engineer doing it on a Friday afternoon, but it happens within minutes of the bot opening the PR — before drift sets in.

If you don't want a tool, the manual version is: assign every red Dependabot PR to a human within 24 hours. Owner gets 30 minutes to either fix or close-with-reason. The PR doesn't sit unassigned. Ever. This is hard to enforce by policy, which is why most teams give up on it after a fortnight.

For the longer version of how this compares to other tools, I wrote Dependabot vs Renovate vs RepoWarden.

Fix 3: route ownership automatically

If you don't have a CODEOWNERS file, that's your Monday morning. If you do, audit it for staleness — most are at least one team-restructure out of date.

A minimum viable CODEOWNERS:

# .github/CODEOWNERS
*                       @your-org/platform
/apps/web/              @your-org/frontend
/apps/api/              @your-org/backend
/infra/                 @your-org/platform
package.json            @your-org/platform
package-lock.json       @your-org/platform

Then enable auto-assignment on Dependabot PRs:

# .github/dependabot.yml (add to each update block)
    reviewers:
      - "your-org/platform"
    assignees:
      - "your-org/platform"
    labels:
      - "dependencies"
      - "needs-triage"

Now every Dependabot PR has a real human group attached on creation. Combine this with a Slack notification to that team's channel and the "no clear owner" failure mode mostly evaporates. It doesn't make the merge happen. It does make the lack of merge visible to a specific human.

Fix 4: 30 minutes on Friday, on the calendar

This sounds trivial. It is the most effective thing on this list.

Block 30 minutes on Friday afternoon. Recurring. Title it "Dep PR triage." One engineer, one screen-share, the team's open Dependabot queue. The rules:

  • Green PR + low risk → merge.
  • Red PR with obvious fix → fix it now.
  • Red PR with non-obvious fix → assign with a due date and move on.
  • Stuck transitive → open a follow-up issue for the parent bump and close the bot's PR.

That's it. 30 minutes, every week, no exceptions. The reason this works isn't because the meeting is magical. It's because the queue is bounded. You're saying out loud: "we are not letting this drift past one week without a human looking at it." That commitment alone changes the dynamic.

If your team won't sustain a 30-minute weekly slot, you have a different problem and no tool will fix it.

The honest take

You can do all four of these and still bleed time. Grouping reduces noise, but the bumps you actually need to think about are still there. Auto-assignment routes the work, but the work still has to be done. Friday triage works for a quarter or two and then someone goes on parental leave and the cadence slips. CI failures are the constant — they don't grow with team size, they grow with dependency surface area, and that only goes up.

The realistic state for most teams is: with all four fixes in place, your median time-to-merge drops from weeks to days, and the queue stays at a manageable size instead of compounding. Your worst case is still a transitive stuck behind a parent that nobody has cycles to upgrade. That's the residual problem.

For my regulated estate, the residual was big enough to matter — half the security findings I needed to close for SOC 2 were stuck not because the fix was hard, but because the fix had drifted past the point where a human wanted to pick it up. That's the specific shape of pain I'd recommend reading about in the SOC 2 patching SLA post if compliance is your driver.

If it's not — if you just want the queue to stop being depressing — start with Fix 1 and Fix 4 this week. They cost nothing and they get you 60% of the benefit. Layer Fix 3 in next sprint. Fix 2 is the one you'll either solve with a tool or accept as ongoing toil.

If you want the audit version

I built RepoWarden because after running this workflow manually for a year I wanted the boring parts done by a machine. Point it at a repo, no signup, and it'll tell you how many of your open dependency PRs would auto-fix on Monday morning. Useful as a diagnostic even if you never adopt the product — it tells you the actual size of your CI-failure tax.

Either way: clear the queue. The longer those PRs sit, the harder they get to merge. That's the whole problem in one sentence.

Free instant repo audit

See how many engineering hours you'd reclaim

Paste any public GitHub repo. We scan for outdated dependencies, committed secrets, missing CI, weak coverage and more — then estimate the engineering time RepoWarden would save you.

No sign-up required to see the report · Public repos only · Read-only public API

Ready to automate your dependency updates?

RepoWarden keeps your repos secure and up to date — with supply chain protection, automated testing, and clean PRs.

Get started free