
ADO Pilot connected to your Azure DevOps organization — the dashboard shows a successful connection — but no pull requests have ever been reviewed. Unlike [Webhook 401s and reviews stopped firing](webhook-401.md), which covers reviews that _used to work_ and then stopped, this page covers reviews that **never started** in the first place.

## Symptom

### What you observe

The dashboard's **Integration** settings page shows a connection, but a banner appears. Its color tells you the blast radius:

- **Amber banner (some projects affected):** _"ADO Pilot can read your repositories but couldn't create the service-hook subscription for [N] project(s) ([names]) — pull requests are still being reviewed in your other projects, but new PRs in [these project(s)] won't be."_ Reviews are working normally everywhere else — only the named project(s) are affected.
- **Red banner (no projects working):** _"ADO Pilot can read your Azure DevOps organization but couldn't create any service-hook subscriptions — pull requests aren't being reviewed anywhere in your organization right now."_ Nothing is being reviewed anywhere yet.

Either way, the **Service Hooks** table lists the affected project(s) with a specific reason next to them instead of a normal **active** status, and no pull request in those project(s) has ever received a review or a status check, even brand-new ones.

Both banners share the exact same root cause and fix below — the color only reflects how much of your organization is currently affected, not a different problem.

### What's happening behind the scenes

Reading your code and posting review comments is a different Azure DevOps permission from _creating the subscription that delivers pull-request events to us in the first place_. The identity ADO Pilot uses — your personal access token's owner, or the ADO Pilot service principal — successfully authenticated and can read the repository, but Azure DevOps rejected the one-time request to create that subscription with a permission error. Nothing about your PR review setup is broken; the very first step, receiving the event, never completed.

## Why it happens

Creating or editing a service-hook subscription requires the **Edit Subscriptions** and **View Subscriptions** permissions in Azure DevOps. By default, only **Project Administrators** (or, at the organization level, **Project Collection Administrators**) hold these — see Microsoft's [Service Hooks FAQ](https://learn.microsoft.com/en-us/azure/devops/service-hooks/overview?view=azure-devops#q-what-permissions-do-i-need-to-set-up-a-subscription). The **Contributors** group, which covers reading code and posting pull request comments, does **not** include it. If the identity ADO Pilot uses was only ever added to Contributors, subscription creation fails even though everything else about the connection looks healthy.

## How to fix it

### If you connected with the ADO Pilot service principal

The recommended fix, run once as a **Project Collection Administrator**, grants the service principal **Edit Subscriptions** and **View Subscriptions**, scoped to just the affected project:

```bash
az rest --method POST \
  --url "https://dev.azure.com/<YOUR_ORG>/_apis/accesscontrolentries/cb594ebe-87dd-4fc9-ac2c-6a10a4c92046?api-version=7.1-preview.1" \
  --resource 499b84ac-1321-427f-aa17-267ca6975798 \
  --headers "Content-Type=application/json" \
  --body '{"token":"PublisherSecurity/<PROJECT_ID>","merge":true,"accessControlEntries":[{"descriptor":"Microsoft.VisualStudio.Services.Claims.AadServicePrincipal;<YOUR_ENTRA_TENANT_ID>\\<SP_OBJECT_ID>","allow":3,"deny":0}]}'
```

Keep the `\\` between the tenant ID and object ID exactly as shown (a literal backslash the JSON escapes), and leave `499b84ac-…` as-is — it tells `az rest` to request an Azure DevOps token. See [Setting up Service Principal auth, Step 2](../connecting-ado/service-principal-setup.md#step-2-add-the-service-principal-to-your-azure-devops-org) for how to find `<SP_OBJECT_ID>` and `<PROJECT_ID>`, the per-project repetition for multi-project orgs (Azure DevOps checks this permission per project — there's no org-wide equivalent), and the no-CLI (Project Administrator) alternative.

### If you connected with a personal access token (PAT)

The Azure DevOps **user** whose PAT you connected needs the **Project Administrator** role on the affected projects. This is an **organization permission on that user**, not a PAT scope you can select when generating the token — no combination of PAT scopes grants it.

{% callout type="info" title="Why this isn't a PAT-scope problem" %}
It's tempting to assume a wider PAT scope selection would fix this, but service-hook management isn't exposed as a selectable PAT scope at all. The permission lives on the connected user's Azure DevOps role, independent of what scopes the token itself carries.
{% /callout %}

### Confirm it worked

Once the permission is granted, open the dashboard **Integration** settings page:

{% steps %}

### PAT connections

Click **Resync**. This immediately re-creates the missing subscription using your existing token (it does not change your PAT) — the banner and per-project reason clear right away on success.

### Service Principal connections

Click **Re-check**. This re-probes your organization directly and refreshes the status right away, but it's a read-only check — it doesn't itself re-create the subscription. If you grant the permission within about 48 hours of connecting the service principal, the banner clears automatically within a few minutes once ADO Pilot's background retry succeeds. Past that window the automatic retry has stopped, so open a support request below and we'll re-arm it for you.

{% /steps %}

{% callout type="info" title="Do we keep retrying on our own?" %}
**Service Principal:** yes, but only for about 48 hours after the service principal was connected — during that window, ADO Pilot keeps retrying subscription creation in the background on its own, so the banner clears itself once the permission takes effect, even if you never click Re-check. Past that window, automatic retries stop and you'll need to open a support request (below) so we can re-arm activation. **Personal access token:** no — nothing re-creates the subscription for you; you need to click **Resync** yourself after granting the permission. Either way, every account admin gets an email once the failure is detected, then again roughly daily until it's fixed, so it's not something you have to catch by watching the dashboard.
{% /callout %}

### Still stuck?

If **Re-check** or **Resync** keeps reporting the same failure after you've granted the permission above, double check it landed on the **same project(s)** the banner names — a permission granted at the wrong project, or only at a team level, won't take effect. If you previously granted this permission organization-wide using the `PublisherSecurity/tfs` token, note that Azure DevOps evaluates the subscription-create permission per project — the org-wide token does **not** satisfy it. Apply the grant above once per affected project using that project's own `PublisherSecurity/<PROJECT_ID>` token. If it still doesn't clear, open a [support request](../trust/support-and-contact.md) with your Azure DevOps organization name, the affected project name(s), and your ADO Pilot dashboard email.

## How to prevent it

Grant the service-hook permission up front during setup, alongside Contributors — the project-scoped Service Hooks grant is recommended (see [Setting up Service Principal auth, Step 2](../connecting-ado/service-principal-setup.md#step-2-add-the-service-principal-to-your-azure-devops-org)) — or see [Service hooks and webhooks](../connecting-ado/service-hooks-explained.md) for what ADO Pilot needs and why.


