Troubleshoot Microsoft Entra directory sync
Resolve connection, group-picker, scope-change, and sync errors when syncing users from Microsoft Entra.
Most Microsoft Entra (Azure AD) sync problems surface as a toast on the Integrations page or a stalled status badge in Synced directories. This page walks through the specific errors Hook can show — during the initial consent handshake, while picking groups, when you change which groups sync, and when a sync run fails — and tells you exactly what each one means and how to clear it. Use it when a connect attempt bounces back with an error, a sync won't start, or users you expected don't appear.
If you haven't connected Entra yet, start with Sync users from Microsoft Entra — this page assumes you already know that flow.
Before you start
Prerequisites
- You're signed in to Hook as an org admin, with the right organization selected in the sidebar org switcher if you manage more than one.
- You can reach Settings → Integrations
(
/org/settings/integrations), where every error toast and status badge in this guide appears. - For consent errors, you may need an identity admin who can grant tenant-wide consent in Entra on standby.
Consent errors after clicking Connect
When you click Connect on the Microsoft Entra tile, Hook hands off to Microsoft's admin-consent screen and waits for the redirect back. If the handshake doesn't complete cleanly, Hook drops you back on the Integrations page with a toast. The exact wording tells you what failed:
| Toast you see | What it means | What to do |
|---|---|---|
Admin consent was not granted. Connect again and accept the requested permissions. (consent_denied) | You (or the admin who approved) cancelled the Microsoft prompt, or the account couldn't grant tenant-wide consent. | Click Connect again and sign in with an account that can approve consent for the whole tenant. |
The connection link was invalid or expired. Please start the connection again. (invalid_state) | The signed handshake link Hook minted didn't verify — usually because it expired, or the consent screen sat open too long. | Start the connect over from the tile. The link is valid for 10 minutes, so don't leave the Microsoft prompt open past that. |
The tenant returned by Microsoft did not match the expected value. (tenant_mismatch) | Microsoft sent back a different tenant than the one Hook started the connect for, or the callback came back without a tenant at all. | Make sure you approve consent in the same tenant you intend to sync, then retry. |
We could not reach Microsoft. Please check your network and try again. (network_error) | Hook couldn't talk to Microsoft to confirm the consent. | Wait a moment and click Connect again. |
Something went wrong. Please try again. (unexpected) | A catch-all for anything not in the categories above. | Retry the connect. If it keeps failing, contact support. |
Hook proves consent before going Connected
Hook does not mark the tenant Connected just because Microsoft says
the prompt was approved. It first acquires a token against your tenant
to confirm the permissions actually landed — so a consent_denied or
tenant_mismatch toast means the connection was not established and
no half-connected row is left behind.

"Microsoft Entra is already connected"
If you click Connect while another Entra tenant is already active, the toast reads:
Microsoft Entra is already connected. Disconnect the current tenant first to connect another. Multi-tenant support is on the roadmap.
Hook supports one active directory provider per organization today. To switch to a different tenant, find the connected row in Synced directories, click Disconnect, confirm, and then connect the new tenant. Previously synced groups are preserved across a disconnect, so this is safe.
Reconnect can hit the same wall
The Reconnect and Retry buttons on an existing row run the same check. If you see Another directory is already connected for this organization, a second tenant is in the way — disconnect it first.
Group-picker limits
The picker at /org/settings/integrations/microsoft-entra/groups has a
few hard limits worth knowing before you blame a sync for "missing" data.
Only the first 1,000 groups load
The picker loads up to the first 1,000 groups from your tenant. If your directory has more, a yellow callout reads We loaded the first 1,000 groups. Larger-directory support is on the way. Use the search box (by name, email, or type) to find the groups you need — search filters the loaded set, so a group beyond the first 1,000 won't appear there yet.
You can select at most 200 groups
Selecting more than 200 groups blocks the Continue to preview step with the toast Please select fewer than 200 groups. Large-org support is coming soon. Past 100 selections you'll also see an informational note that large selections may take longer to preview — that one is just a heads-up, not a blocker.
Nested groups must be selected separately
The sync engine enumerates direct members only. If a group contains other groups as members, the picker shows a N nested groups badge with the tooltip Select separately to include their members. Those nested groups' members are not pulled in automatically — if you want them, find each nested group in the list and check it too.

"A sync is already in progress"
Hook allows only one sync run per directory connection at a time. If you
trigger a sync — or try to commit a scope change — while another run is
still going, Hook returns a sync_in_progress result and shows a toast.
The exact wording depends on where you triggered from:
- From Sync now in the workspace (an HTTP 409 from the sync endpoint): A sync is already in progress for this directory.
- From Save scope change on the preview screen: A [kind] is already
running for this connection. Wait for it to finish, then try again.
(where
[kind]names the run that holds the lock, e.g. "delta").
This is expected, not a fault. Wait for the active run to finish (the Syncing badge in the workspace pane reflects an active run), then trigger again. The lock applies across all run types — an initial sync, a delta sync, and a scope change all count as "in progress."
Scope-change errors
Reopening Manage groups and changing your selection commits a scope resync. The preview screen for a scope change is stricter than the first-time preview, because removing groups can deactivate people.
Removing a group deactivates orphaned users
When your change removes a group, the preview lists each affected member. Anyone whose only directory-group membership came from a removed group is tagged Will be deactivated, and a banner totals them: N users will be deactivated because they have no remaining directory-group memberships after this change. Users who also belong to a group you're keeping (or to a group you're adding in the same change) are not deactivated.
Removing all groups requires the acknowledgement checkbox
If your change leaves zero groups selected, Hook shows a red alert — This will deactivate every user from this directory connection — with a required checkbox: I understand this will deactivate N users. The Save scope change button stays disabled until you tick it. Affected users can be restored later by re-selecting their groups.
A single added group can't exceed 50,000 members
Each newly added group is capped at 50,000 members. If one is
larger, the commit fails with group_too_large and Hook names the
offending group and its member count. Split the membership in Entra or
pick a smaller group, then retry the scope change.
Member counts come from Entra at pick time
The member count Hook checks against the 50,000 cap is the value Entra reported when you loaded the picker (or the last cached count for a group you previously synced). It is not re-fetched at save time, so a group that grows past the cap between picking and saving may slip through and be caught later by the sync engine instead.

When a sync run fails
A failed run shows a Sync failed badge in the sync block of the workspace pane. How you recover depends on the kind of run.
- Failed scope change (scope resync). A failed scope resync has no recovery path from the regular Sync now button — that button only triggers a normal initial or delta sync. Instead, use the dedicated Retry scope sync button that appears next to the failed run (it only shows while the latest run is a failed scope resync). It re-runs the exact same group change you committed, so you don't have to redo your selection.
- Enqueue failures. If Hook saved your selection but couldn't hand
the job off to start it (an
enqueue_failedresult), your selection is still committed — the run just didn't kick off. For a scope change, the toast reads Selection saved but the sync could not be queued. Try clicking Save again to retry. — so click Save scope change again, or use the Retry scope sync button on the integrations page. For a regular sync, click Sync now again. Because your group selection is the source of truth, a re-run lands on the same result.

Common pitfalls
- Members appear after the next sync, not instantly. Saving a selection or committing a scope change triggers a sync; it doesn't populate users synchronously. Counts in Synced directories and the All users tab fill in as the background run completes.
- A missing tenant display name is harmless. If the connected row
shows the generic provider label instead of your tenant's name, Hook
couldn't read the tenant's display name (it lacks the
Organization.Read.Allpermission). The connection itself is still valid and syncing — this is cosmetic. Disconnecting and reconnecting with that permission granted refreshes the label. network_errorandunexpectedare usually transient. Both clear on a retry more often than not. Only escalate if a clean retry reproduces the same category.
Related
Sync users from Microsoft Entra
The end-to-end connect, pick, preview, and confirm flow this page troubleshoots.
Manage directory connections
Disconnect, reconnect, and manage the synced directories for your org.
Authorize recipient domains
Approve the email domains your synced users share so campaigns can reach them.