Troubleshooting Permission Sync Failures with Multiple Private GitHub App Installations
Problem
Users report that repository or user permissions are not syncing correctly. Typically this surfaces as:
- Private repositories from one or more GitHub organizations not visible to users who should have access
- Search returning
repository does not existor repos appearing inaccessible after permission sync - Code Insights errors referencing
github.com/org/repo@(empty revision) - Repeated WARN-level logs from
repos/syncer.go: "finished listing repositories from external service"
This commonly occurs when an organization uses multiple private GitHub Apps — one per GitHub org — rather than a single public app installed across all orgs.
Background
By default, Sourcegraph creates private GitHub Apps, which can only be installed on the org or user account they were created in. When code is spread across multiple GitHub orgs, teams sometimes create separate private apps per org. This setup requires careful configuration to ensure permissions sync correctly for all users across all apps.
Refer to the official docs for the expected configuration: Configuring Multiple Private GitHub Apps for Sourcegraph.
Debug Steps
1. Verify GitHub-side permissions and roles
Confirm the following on GitHub for each app installation:
- The GitHub App has Repository permissions → Contents: Read (required for gitserver to clone repos)
- The GitHub App has Repository permissions → Metadata: Read (always required)
- For permission syncing, the app requires Organization permissions → Members: Read
- The GitHub App is installed with All repositories access — not "Selected repositories" — unless you have intentionally scoped it
- The person who installed the app on the org is an organization owner (only org owners can install GitHub Apps on an org)
2. Confirm the GitHub App is correctly set up in Sourcegraph
- Go to Site admin → Repositories → GitHub Apps and verify each app appears and shows the correct installation(s)
- Each org's installation should have an active code host connection — if "Add connection" was never clicked after installing the app on an org, repos will be enumerated but never cloned
- Confirm the app's webhook is active and receiving events (check Site admin → Repositories → GitHub Apps → [App] → Webhook)
3. Check auth.providers in site config for each app
This is the most common misconfiguration with multiple private apps. Each GitHub App must have its own separate entry in the auth.providers block of site config. A single OAuth entry will not cover multiple apps.
"auth.providers": [ { "type": "github", "url": "https://github.com", "clientID": "<App 1 Client ID>", "clientSecret": "<App 1 Client Secret>", "allowSignup": true }, { "type": "github", "url": "https://github.com", "clientID": "<App 2 Client ID>", "clientSecret": "<App 2 Client Secret>", "allowSignup": true } ]
Check for:
- Missing entries — if an app has no corresponding entry in
auth.providers, users will not be able to authorize it and permission syncing will not work for that app's repos - Wrong URLs — the
urlfield must exactly match the GitHub instance URL used for that app (e.g.https://github.comor your GitHub Enterprise Server URL) - Mismatched Client IDs / Secrets — ensure each entry's
clientIDandclientSecretcorrespond to the correct app
4. Confirm users have authorized each app
With multiple private GitHub Apps, users must individually authorize each app to allow Sourcegraph to sync their permissions. Unlike a single public app, private apps do not share authentication across installations.
Users can do this by going to: User Settings → Account Security and verifying all required GitHub Apps appear as connected external accounts. If any app is missing, the user needs to connect it from there.
Resolution
- Correct any misconfiguration identified above (missing
auth.providersentries, wrong URLs, incorrect GitHub App permissions, missing "Add connection" in Site Admin) - Ask the affected user(s) to go to Settings → Account Security, disconnect the affected GitHub App connection, then reconnect it. This forces a fresh OAuth authorization against the corrected config
- Permissions will be corrected on the next scheduled permission sync
- If resolution is urgent, trigger a manual permission sync: go to Site admin → Permissions and click Schedule now for the affected user or repository