MergeMe logoMergeMe
Published on

GitHub CODEOWNERS Notifications in Slack: Fix Missing Requests

Authors
  • Name
    Maruan

An engineer opens a pull request that alters an authentication service, tags nobody, and expects the security team to appear. Three days later, the code sits untouched. When someone asks in Slack why the team never reviewed the patch, the answer is always the same: nobody saw a ping.

Teams usually assume their chat bot failed. A lead runs a slash command, reconnects an integration, or blames Slack rate limits. Then the next pull request repeats the exact same silence.

Missing GitHub CODEOWNERS notifications in Slack are rarely caused by one mysterious failure. Engineers treat GitHub and Slack as a single pipeline when they're two independent systems. When an owner isn't notified in Slack, one of two things went wrong: GitHub never requested the owner on the pull request, or GitHub added them and Slack dropped the alert. You can't fix alert delivery until you confirm reviewer selection actually happened.

Two separate systems: who GitHub requests vs what Slack shows

Debugging this problem starts with a clean mental separation. GitHub runs a deterministic rules engine when a pull request opens. That engine inspects the files modified, reads a flat file in your repository, checks team memberships, and populates the Reviewers box in the pull request sidebar.

Slack knows nothing about this computation. Slack only acts on webhook events emitted after GitHub finishes modifying the pull request record. If GitHub's rules engine fails to add an owner, GitHub sends no reviewer assignment payload to any connected service. Your chat integration won't ping the user because GitHub told it nobody was assigned.

The reverse also happens. GitHub might execute CODEOWNERS perfectly, populate the Reviewers box with three senior engineers, and fire the pull_request.review_requested event. If the chat application doesn't know which Slack user ID corresponds to that GitHub username, or if your channel settings mute bot notifications, the alert dies on delivery.

When a notification fails, don't start by adjusting Slack channel settings. Open the pull request on GitHub.com first. If the owner's name or team handle is absent from the Reviewers sidebar, you have a GitHub CODEOWNERS bug. If the name is in the sidebar but silent in your channels, you have a Slack routing or identity mapping bug. Tools like MergeMe sit on the delivery side of this boundary, turning those GitHub events into one updating card per PR in Slack, but they depend on GitHub getting the initial review request right.

How CODEOWNERS selects reviewers: file location, base branch, and last-match-wins patterns

GitHub evaluates the CODEOWNERS file using strict, non-configurable parsing rules. If your file breaks these constraints, GitHub ignores it silently. No failed build, no warning banner.

GitHub looks for the file in three exact locations, checked in this priority order: .github/CODEOWNERS, the repository root CODEOWNERS, and docs/CODEOWNERS. If you put the file inside a subfolder like .github/workflows/ or config/, GitHub never reads it. Keep it in .github/CODEOWNERS so it sits next to your other repository automation.

The most common misunderstanding involves branches. GitHub evaluates CODEOWNERS against the base branch of the pull request, not the head branch containing your code changes. Say you write a brand new CODEOWNERS file on a branch named feat/add-codeowners and open a pull request into main. GitHub evaluates the file on main. Because main doesn't contain your file yet, GitHub assigns zero reviewers to your pull request. You have to merge the file into the base branch before automated assignments work.

Pattern matching follows gitignore rules with one critical override: the last matching pattern takes absolute precedence. Consider this common mistake:

* @platform-team /services/auth/* @security-team /services/* @core-backend

An engineer modifying /services/auth/token.go might expect @security-team to be requested. Instead, GitHub assigns @core-backend. The third line matched the path and superseded the more specific rule above it. To fix this, put generic catch-all rules at the very top of the file and narrow directory paths at the bottom.

Why owners are never requested: draft PRs, invalid or non-visible teams, missing write access, and files over 3 MB

Even when your file location and pattern syntax are pristine, GitHub has hard business logic that silently drops ownership assignments.

Draft pull requests don't request reviewers. GitHub does not automatically request code owners to review draft pull requests; they are notified when the draft is marked ready for review. When an author converts the draft to 'Ready for review', GitHub runs the rules and assigns owners. If an engineer opens a draft and wonders why their tech lead got no Slack ping, the system is working as designed.

If the tech lead who owns /billing/ opens a pull request that touches the billing directory, GitHub strips that lead from the reviewer request list. If that lead is the sole owner of the directory, the Reviewers sidebar stays empty.

Team visibility and repo permissions are another quiet failure point. For CODEOWNERS to assign a GitHub team, two things must be true. First, the team needs explicit write access to the repository. Read access isn't enough. Second, if you use nested or child teams, the parent organization structure must grant visibility. CODEOWNERS can't request secret teams if the pull request creator lacks permission to view team membership.

Finally, check your file size. GitHub enforces a hard 3 MB limit on CODEOWNERS files. If your repository runs large monorepo generators that write tens of thousands of lines of ownership rules, GitHub skips the file completely once it crosses 3 MB. It won't tell you the file exceeded limits. It just stops assigning reviewers.

Team review requests vs notification subscription: team settings, auto-assignment, and Slack channel subscriptions

When you specify a team handle like @org/backend in CODEOWNERS, GitHub doesn't treat it as a static group of individuals. Its behavior depends entirely on your GitHub Team settings.

Under your team settings on GitHub, go to Code review assignment. If this feature is disabled, GitHub requests the entire team as a single reviewer object. The pull request shows @org/backend in the Reviewers box. Your Slack integration receives a team-level request. If individual engineers expect personal pings in Slack, they won't get them under this configuration.

If you enable Code review assignment, GitHub runs round-robin or load-balancing logic to select individual team members. In this mode, GitHub assigns specific developers (for example, @alice and @bob) instead of the team container. The Reviewers sidebar shows the individuals, and GitHub emits assignment events for those specific accounts. This matters for a clean pull request review handoff, because accountability shifts from a collective bystander effect to named engineers.

Watch your team membership settings. If team auto-assignment is enabled, GitHub lets members mark themselves as 'Busy' or excluded from assignment. If three of your four team members have the busy status toggled, GitHub routes every pull request to the fourth person. If all members are marked busy, GitHub falls back to requesting the parent team or leaves the reviewer list blank, which means no individual Slack pings.

Channel subscriptions add the final hurdle. If your Slack app only listens for repository-level events in #eng-prs, but your developers mute that channel, notifications go unread. Team-level assignments in GitHub have to line up with specific destination channels or direct message alerts.

A minimal CODEOWNERS example and a safe test checklist (record the GitHub Reviewers sidebar first, then check Slack)

Don't test ownership rules on active feature branches during production hours. Set up a controlled test with a minimal configuration so you can verify each boundary step.

Here is a minimal, reliable .github/CODEOWNERS structure:

# Global fallback owner
* @org/core-leads

# Specific component owners
/packages/auth/ @org/security-team
/packages/billing/ @alice

Commit this file directly to your default branch (main or master). If you test this on an unmerged branch, your pull request checks against the older default branch and fails the test immediately.

Run through this verification checklist:

  1. Ensure @org/security-team and @org/core-leads have write permissions in your GitHub repository access settings.

  2. Ensure the test author opening the pull request is not @alice and is not the sole member of @org/security-team.

  3. Create a branch named test/codeowners-check off main.

  4. Create a dummy file at packages/auth/test.txt with a single line of text.

  5. Open a pull request against main. Don't mark it as a draft. Open it as 'Ready for review'.

  6. Stop. Don't open Slack.

  7. Inspect the GitHub pull request page. Look at the Reviewers sidebar on the right-hand rail.

  8. Record what you see. Does the sidebar list @org/security-team or the specific members chosen by auto-assignment? Take a screenshot.

  9. If the sidebar is populated correctly, wait sixty seconds, then inspect your target Slack channel or direct messages.

Verify the Reviewers sidebar before touching Slack and you cut the debugging space in half.

Reading the result: when to fix CODEOWNERS, when to fix Slack routing, and where to look for identity mapping and private-repo permissions

Once you finish the checklist test, your path splits cleanly based on what you recorded in step 8.

If the Reviewers sidebar on GitHub was empty, stop debugging Slack. The issue sits in your repository configuration. Verify the path syntax in your file, make sure the file is merged into your base branch, and confirm your teams have write access to the repo. If you used a team name, check whether the team has been made secret or deleted.

If the Reviewers sidebar listed the correct users or teams, but no alert appeared in your workspace, your Slack integration dropped the payload. Three issues account for nearly all delivery failures at this layer.

First, check private repository visibility. If your repository is private and the bot lacks authorization to read private metadata, the integration ignores webhook events from that repository. For an in-depth audit of these repository grant settings, read our guide on how to fix GitHub Slack private repo notifications.

Second, check username to Slack identity mapping. GitHub knows your developer as @alex-dev, but Slack knows them as U04ABC123. If your integration has no link between those two accounts, it can't translate a reviewer request into a personal DM or an @alex mention in a public channel. Read our guide on how to fix broken @mentions in Slack for code review to resolve user lookup tables.

Third, review channel routing. If an integration posts every pull request to an overloaded firehose channel, engineers mute the noise and miss assignments. MergeMe handles this by delivering Slack notifications for GitHub pull requests and GitLab merge requests, shown as one updating card per PR/MR. The review lifecycle stays in a single message instead of a sprawling thread of disconnected events. The Hobby plan is free forever with 1 channel mapping and 5 user mappings, while the Team plan is £5 per dev seat monthly with a 5 seat minimum.

Conclusion

Stop spending retrospectives debating why pull requests sat unreviewed for days while owners insisted they never saw a ping. The problem is solvable the moment you stop treating GitHub and Slack as a single black box.

Run the test checklist. Check the GitHub Reviewers sidebar first. If GitHub isn't assigning owners, fix your CODEOWNERS file location, write permissions, and last-match syntax on your default branch. If GitHub is assigning owners, audit your Slack app permissions and user mapping.

If your team manages code reviews across GitHub and Slack, connect MergeMe. MergeMe tracks your pull requests and posts them as one updating card per PR in Slack, so code owners get clear visibility without notification noise.

FAQs

Why does GitHub CODEOWNERS not automatically request reviewers on my pull request?

The most common reasons are that the pull request is still a draft, the PR author is the directory owner, the CODEOWNERS file has not been merged to the base branch, or the assigned team lacks write permissions. GitHub also ignores CODEOWNERS files larger than 3 MB.

Can GitHub CODEOWNERS ping a specific Slack channel directly?

No. CODEOWNERS identifies GitHub users or teams with repository write access and automatically requests their review on qualifying pull requests; it does not assign reviewers outside GitHub. Pinging a Slack channel requires an external Slack integration that receives GitHub review request events and routes them to your designated workspace channels.

Why did GitHub assign the CODEOWNERS team but Slack did not notify individual members?

If your GitHub Team settings have Code review assignment disabled, GitHub requests the entire team object instead of individual engineers. Many Slack apps only ping individual user mentions. Enable round-robin or load-balancing assignment in GitHub Team settings to assign and ping named individuals.

How do I fix missing GitHub notifications in private Slack channels?

Ensure the Slack bot has been explicitly invited to the private channel with the `/invite @botname` command. Additionally, verify that your Slack app has been granted access to private repositories inside your GitHub organization settings.