Skip to main content

Troubleshooting first-time setup

Common issues encountered during initial tenant setup, with the exact fix for each. If you hit something not on this list, search this repo's docs/ or contact your operator.


SSO

AADSTS50011: The redirect URI '...' specified in the request does not match the redirect URIs configured for the application

Cause: the redirect URI EnClaw sent to Azure AD doesn't match anything in the app registration's allowed list.

Fix: Entra admin → App registrations → find the app by client ID (shown in the error message) → AuthenticationWebRedirect URIs → add the exact URL from the error. Save.

If you're a platform operator running multiple SaaS environments against the same app, register all four callback URLs at once:

https://your-org-api.enclaw.com/api/auth/sso/callback
https://app-api.enclaw.com/api/auth/sso/callback
https://stage-app-api.enclaw.com/api/auth/sso/callback
https://dev-app-api.enclaw.com/api/auth/sso/callback

AADSTS65001: The user or administrator has not consented to use the application

Cause: Application permissions (not delegated) were added but admin consent wasn't granted.

Fix: Entra admin → App registrations → your app → API permissions → click ✓ Grant admin consent for [Tenant]. The lock icon next to each Application permission should turn into a green check.

AADSTS700016: Application with identifier 'xxx' was not found in the directory

Cause: the client ID in the EnClaw SSO config doesn't exist in the Azure AD tenant.

Fix: double-check the client ID — easy typo target. It's the Application (client) ID on the app registration's Overview page, not the Object ID.

"Sign in with [provider]" button never appears on /login

Cause: the SSO config row in /sso-providers isn't marked active, OR the email you typed doesn't match the SSO config's email-domain rule (if you've set one).

Fix: /sso-providers → edit the row → tick Is active. If you've set an explicit email-domain allowlist, make sure your email matches.

After SSO sign-in, the URL bar lands on /login?error=...

Cause: the SSO callback received a valid token from the IdP but the EnClaw side rejected it. Reasons vary — most common is auto-provision is off and the user doesn't exist locally yet.

Fix: check the error text in the query string (URL-decoded). If it's "User not found", either invite the user first or enable auto-provision in your SSO config.


Invites

"Join undefined" button and the tenant name is missing

Cause: old API version returning the wrong response shape ({tenant: {...}} instead of flat tenantName).

Fix: redeploy your environment — fix landed in the invites service. If you've redeployed and still see this, your CDN may be caching the JS bundle. Hard-refresh (Ctrl+Shift+R).

"Forbidden resource" 403 when creating an invite

Cause: the operator UI's /admin/saas/tenants/[id]/invites route used to gate strictly on platform_admin, rejecting super_admin actors.

Fix: redeploy — both roles now pass the guard. If you can't redeploy, switch your account to platform_admin instead of super_admin (same effective privileges in SaaS mode).

"New user invites require password + name. Send them in body" error

Cause: the previewInvite endpoint wasn't returning isNewUser, so the UI sent a bare-token accept body, but the server treated the email as new and required password+name.

Fix: redeploy. If you can't redeploy, you can work around manually by hitting POST /api/invites/accept with { token, name: "First Last", password: "Something1!" } via curl/Postman.

Invite shows red "No email provider configured" banner

Cause: no active Teams channel integration with the send_email allowed action.

Fix: /integrations → Microsoft Teams — connect it, tick Send emails from EnClaw inbox under Allowed Actions, set Outlook Send-From Email, save. Subsequent invites will show the green "Email sent" banner.

In the meantime, the invite is still valid — copy the link from the dialog and share it manually.

Cause: the rawToken in the URL is wrong (truncated, transcription error) OR the invite genuinely expired (default 7 days).

Fix: reissue from /users → Invites → click the row's Reissue button. The old link is revoked, a fresh token + URL is generated. The new email goes out via the same path.


CORS / network

Browser DevTools shows CORS error: access-control-allow-origin doesn't match

Cause: the API was deployed without the custom-domain set, so it accepts CORS only from the default ACA FQDN. Browser at <env-prefix>app.enclaw.com gets blocked.

Fix: your operator needs to redeploy with customWebDomain passed to Bicep. Operator-side commits landed in late May 2026; if your deployment predates that, ask the operator to redeploy.

Login form POSTs to http://localhost:3001/api/auth/login

Cause: the web Docker image was built without NEXT_PUBLIC_API_URL baked in. Next.js bakes NEXT_PUBLIC_* env vars at build time, not runtime.

Fix: operator-side issue. The build job must pass --build-arg NEXT_PUBLIC_API_URL=https://<your-api-host>/api. Fix landed late May 2026.

Cannot GET /health returning 404 — is the API alive?

Yes, that 404 means the API is responding. The endpoint just isn't /health — try /api/healthz or visit /api/auth/login-options (POST) to confirm. A real "API is down" symptom is timeout or "connection refused", not a 404.


LLM providers

Test button on the provider row shows red "auth failed"

Cause: API key is wrong, expired, or out of region.

Fix: rotate the key in the provider's console, paste fresh, save. For Azure OpenAI: confirm the endpoint URL is for the region your deployment is in.

Models picker on the agent edit page is empty

Cause: the provider returned no models. Usually a permission issue — your API key doesn't have access to any model deployments.

Fix: check the provider console — is at least one model deployed / accessible? For Azure OpenAI: deploy a model in your Azure resource first.


Connectors (My Connections)

Connecting Outlook prompts "Need admin approval" for non-admin users

A non-admin clicks Connect on the Outlook connector in My Connections and Microsoft shows a "Need admin approval — EnClaw needs permission to access resources in your organization that only an admin can grant" page instead of the normal consent screen. The connection never completes.

Cause: two things have to both be true, and usually one is missing.

  1. The tenant restricts user consent (the common default), so a non-admin can never self-consent to the app — Entra converts the consent screen into "Need admin approval". This is fixed once, org-wide, by an admin granting consent for the app.
  2. The connect flow was sending prompt=consent on every authorization. That forces Entra to re-run the full consent ceremony every time and ignores the admin consent grant — so even after an admin consents, non-admins still hit the wall. Fixed in code by using prompt=select_account (see apps/api/src/modules/integrations/integrations.controller.ts, startMicrosoftOAuth).

Fix:

  1. Grant admin consent on the app registration — not the Enterprise application blade. The Enterprise application → Permissions page shows status only and bounces you with "To configure requested permissions for apps you own, use the app registration." Go to Entra admin → App registrations → EnClaw → API permissions → click ✓ Grant admin consent for [Tenant]. Every permission row should flip to a green "Granted for [Tenant]". The connector reuses the shared Teams app registration (the teamsAppId on the teams channel_integrations row), so this single grant covers all users.
  2. Confirm the delegated scopes are registered. The connect flow requests these delegated Microsoft Graph scopes (built from the connector's allowed actions in startMicrosoftOAuth): openid, profile, email, offline_access, Mail.Read, Mail.ReadWrite, Mail.Send, Calendars.Read, Calendars.ReadWrite, Tasks.Read, Tasks.ReadWrite, Notes.Create, Notes.Read, Notes.ReadWrite, Files.Read, Files.ReadWrite. If a user enables an action whose scope isn't on the app registration, that connection re-prompts even after admin consent — add the missing delegated permission, then re-grant consent.
  3. Ensure prompt=consent is not being sent. The start endpoint must use prompt=select_account (or omit prompt). prompt=consent re-triggers consent on every connect and defeats the admin grant.
  4. Have the user retry My Connections → Connect Outlook. They should now get an account picker and the connection completes silently.

Granting admin consent on this app consents the entire permission set at once, including broad application permissions (Group.ReadWrite.All, User.Read.All, Sites.Manage.All, Chat.ReadWrite.All, Mail.Send as-any-user, etc.). That is expected for the shared Teams/bot/SSO app registration, but confirm the app legitimately needs all of it before clicking.


When to escalate to EnClaw support

  • The error mentions an internal-sounding identifier (AADSTS, tenant_id, agent_id) and the fixes above don't apply.
  • The web app loads but the dashboard is empty and DevTools shows persistent 500s from the API.
  • You hit a Provider rejected the message banner on every invite even after fixing the Teams send_email toggle.

Have the timestamp, request ID (DevTools → Network → the failing request → Response headers → x-request-id), and your tenant ID ready when you contact support — it dramatically speeds up diagnosis.