MergeMe logoMergeMe
Published on

Fix GitHub Slack Private Repo Notifications

Authors
  • Name
    Maruan

You type /github subscribe owner/repo into your Slack channel, GitHub confirms, and then nothing happens. A developer opens a pull request thirty minutes later. Slack stays quiet. An engineer pings you asking if the channel webhook broke, while someone else pastes the PR link into chat, where it unfurls cleanly with title, status, and author.

That clean link preview sends teams debugging the wrong problem. Link unfurling runs on your personal GitHub identity via OAuth. Subscription notifications run on the GitHub Slack app installation, which holds its own repository permissions inside your GitHub organization. When GitHub Slack integration private repository notifications fail to arrive, the cause is almost never a transient webhook outage. It's a failure inside one of five separate authorization boundaries.

To diagnose it, isolate each layer instead of re-running subscription slash commands. Here is how the official GitHub Slack integration handles private repositories, where permissions split, and how to check each layer in order.

Why private repo PR notifications go missing: five separate layers

Public repositories rarely break notifications because GitHub doesn't restrict read access across organization boundaries. Private repositories enforce strict access controls at multiple tiers. One missing grant silences pull request alerts, and Slack never shows an error.

Five layers decide whether an event in GitHub reaches your Slack channel. First, the GitHub bot must belong to the Slack channel itself. Second, your personal Slack user must be signed in to a GitHub account with read access to the target repository. Third, if your GitHub organization enforces OAuth app access restrictions, an organization owner must explicitly approve the GitHub Slack integration. Fourth, the GitHub App installation must have repository access granted directly in GitHub organization settings. Fifth, the channel subscription must not filter out the specific pull request event.

Most teams assume that running the subscribe command proves every layer works. It doesn't. The subscribe command checks your personal permissions at the moment you type it. It says nothing about whether the GitHub App can still broadcast repository webhooks to that Slack channel. When any layer drops, the pipeline fails silently.

Layer 1: Is the GitHub app in the Slack channel, especially a private channel?

Slack blocks bot users from reading or posting to private channels unless a channel member explicitly invites them. Say you create a private engineering channel and type /github subscribe owner/repo. Slack might show slash command auto-suggestions, but the GitHub bot still can't post incoming webhook payloads into the channel.

This failure is common during team reorganizations. A team spins up a private channel named #core-backend-prs and subscribes to a private repository. If the bot is absent, messages vanish. Public channels usually add the app automatically when a user invokes an installed slash command, but private Slack channels block automatic bot joins by design.

Check channel membership directly. Type /who in Slack to list the channel members, or open the channel details pane and search the Integrations tab. If @github is missing, run /invite @github. Don't assume the app is present because the /github slash command responded. Slash command responses can run ephemerally for the caller while the bot itself stays locked out of posting regular messages to the channel.

Layer 2 and 3: Personal GitHub sign in versus organization approval

The second and third layers cover identity and organization governance. When you use the GitHub app in Slack, you sign in with /github signin. This binds your personal Slack identity to your GitHub user identity. If you have triage or write permissions on the repository, your personal token lets Slack check repository metadata on your behalf.

That personal token is useless if your company enforces third-party application restrictions. Organizations can enable OAuth app access restrictions to control third-party access to their data. With this restriction active, every OAuth connection needs an explicit grant from an organization owner.

If your organization owner hasn't approved the Slack integration, the app can't reach organization data through your user account. To verify, open your GitHub personal settings, go to Authorized OAuth Apps, and select GitHub + Slack. Look at the organization access list at the bottom of the page. If your organization shows a red cross or a pending request icon, notifications for private repositories will fail. Request approval from that screen, or have an organization administrator grant access under Organization Settings > Third-party Access.

Layer 4: App repository access versus your own access (and why link previews prove nothing)

The most confusing symptom: you paste a private pull request URL into Slack and get a rich card preview, yet automated PR notifications never fire. Engineers see the repository name, branch, and author and conclude the subscription must be working. It isn't.

Link previews and channel subscriptions run on two different architectures. Link previews use the personal OAuth token created during /github signin. If you can read the repository in your browser, the Slack client uses your credentials to unfurl the URL you just pasted. Channel subscriptions, by contrast, are configured in Slack after the integration is installed in the workspace.

The GitHub App installation can be scoped to 'All repositories' or 'Selected repositories'. When a team creates a new private repository, organization policies often leave it unselected in the app settings. You have full administrative access to the repository, so your link previews unfurl instantly. But the GitHub App itself has no read access to that repository. Because the app can't see the repository, GitHub drops the webhook before it leaves their infrastructure.

To fix this, an organization owner must visit https://github.com/organizations/YOUR-ORG/settings/installations, find Slack, click Configure, and confirm that the target private repository appears in the Selected Repositories list. Until the GitHub App installation has explicit repository access, automated notifications will never reach Slack.

Layer 5: Channel subscriptions, default features and filters that hide PRs

Even when permissions and installations line up, configuration can still hide pull requests. The default subscription feature set for the GitHub Slack integration includes issues, pulls, commits:default, releases, and deployments. But if someone earlier changed the channel subscription with /github unsubscribe or added branch filters, pull request notifications can silently drop.

Inspect the exact configuration by running /github subscribe list in the channel. The bot returns the repositories subscribed in that channel along with their active features. If the feature list for your repository doesn't include pulls, PR events are ignored. Restore them with /github subscribe owner/repo pulls.

Branch filters are another common trap. Branch filters in the official integration apply to commit notifications, using settings like commits:main or commits:feature/*. If an engineer ran /github subscribe owner/repo pulls +branches:main, any pull request opened against develop, staging, or a release branch won't trigger a Slack message. Draft pull requests also behave differently depending on configuration. Check whether your channel expects draft PR alerts, and read our guide on how to control when GitHub and GitLab PR/MR cards post to Slack for state-based filtering.

The test PR diagnostic flow: what to do and what you should observe

Don't debug notifications on a live release branch. Run a reproducible test with these steps, in order:

First, invite the bot: run /invite @github inside the designated Slack channel. Second, verify your personal link: run /github signin and confirm authentication succeeds. Third, check existing subscriptions: run /github subscribe list. If the target repository is missing, run /github subscribe owner/repo.

Fourth, trigger an unambiguous test event. In your terminal, check out a new branch on the private repository, make a trivial edit to a README or test file, commit it, and push to GitHub. Open a standard pull request targeting your default branch. Mark it Ready for Review, not Draft.

Watch the channel for 60 seconds. If nothing posts, check these boundaries in order. Run /github subscribe list to verify the repository registered. Next, open your GitHub organization installation settings to confirm the repository is selected. If both pass, check whether your channel routing rules are sending alerts to a different room entirely. Teams with multiple codebases should read how to route GitHub repos and GitLab projects to the right Slack channels to prevent cross-channel misdirection.

Safe escalation: what to send to an admin or GitHub support without secrets

If the diagnostic flow confirms your repository settings are correct but messages still don't appear, you need your GitHub organization admin or Slack workspace admin to step in. Skip vague complaints like 'the GitHub bot is broken'. Hand over an audit trail that pinpoints which permissions tier failed.

Send your administrator this structured checklist:

  1. Target Repository: Provide the exact owner/repo string.

  2. Slack Channel ID: Provide the channel name and the internal Slack Channel ID (found in channel settings at the bottom of the About tab).

  3. Bot Presence: Confirm that @github was in the channel during the test.

  4. Output of Subscription Check: Paste the plain text returned by /github subscribe list.

  5. Test PR URL and Timestamp: Provide the URL of your test pull request and the UTC timestamp when it opened.

Never paste raw personal access tokens, session cookies, or webhook signing secrets into Slack or admin tickets. If an administrator needs to inspect organization webhook delivery logs, point them to https://github.com/organizations/YOUR-ORG/settings/hooks. They can search for the Slack webhook URL, inspect recent delivery payloads, and check whether GitHub recorded a 200 OK or an HTTP failure when the test PR opened. For broader channel permission audits, see our GitLab Slack integration channel permissions audit guide for similar diagnostic patterns.

Optional: if you want one updating card per PR instead (MergeMe)

Fixing permission drops gets notifications working, and then the next headache shows up: noise. The native GitHub Slack integration posts a new channel message when a PR opens, another for reviews, another for status checks, and separate alerts for new commits. In an active engineering channel, ten pull requests can easily produce fifty disjointed messages a day.

MergeMe replaces those scattered alerts with a single updating card per pull request. Instead of five separate replies across a channel, MergeMe keeps one updating card per pull request.

MergeMe connects to GitHub.com, GitLab.com, and self-hosted GitLab within a single Slack workspace, which suits teams running across multiple code platforms. Setup takes minutes and skips the fragmented subscription filters. Teams that need on-premises data control or custom compliance can also run MergeMe on their own infrastructure via self-hosting.

Conclusion

Missing pull request notifications are a permission and routing problem, not a mysterious bug. Isolate the five layers (Slack channel access, user identity, OAuth restrictions, app installation scope, and channel filters) and you can find the break in under ten minutes. If your team is tired of wrestling with slash commands, fragmented thread updates, and lost PR alerts across GitHub and GitLab, try MergeMe. Set up your first channel mapping on the free Hobby plan and swap notification noise for clean, real-time cards.

FAQs

Why do GitHub PR link previews work in Slack if notifications are broken?

Private-repository link previews require connecting your GitHub account to the Slack app, but previews are rendered using the GitHub App's installed repository access. Automated notifications require the GitHub App installation to be granted access to that specific private repository. If the app is missing from repository access settings, notifications will not fire even though your personal link previews display normally.

How do I fix GitHub Slack notifications in a private Slack channel?

Slack prevents external apps from posting in private channels unless invited. Type /invite @github directly inside the private channel. After the bot joins, run /github subscribe owner/repo to register the subscription. Verify the app appears in the channel integration list before running test pull requests.

Why does /github subscribe return an organization access denied error?

Your GitHub organization enforces OAuth App Access Restrictions. An organization owner must approve the GitHub + Slack integration under Organization Settings > Third-party Access. Alternatively, go to your personal GitHub settings, check Authorized OAuth Apps, locate GitHub + Slack, and request organization access from that menu.

How can teams avoid multiple noisy Slack messages for a single GitHub PR?

The official GitHub Slack app groups notifications for each pull request into a thread, with the parent message showing the latest status. Teams looking to eliminate channel noise can use MergeMe, which posts one updating card per PR. MergeMe supports GitHub, GitLab, and self-hosted GitLab in one workspace.