| name | azure-swa-gotchas |
| description | Time saved: 2-4 hours per issue |
| lastReviewed | 2026-04-30T00:00:00.000Z |
Azure Static Web Apps Gotchas
Time saved: 2-4 hours per issue
The Problem
Azure Static Web Apps is powerful but has numerous edge cases that cause silent failures or confusing behavior. The documentation covers the happy path; these are the unhappy paths.
Why This Is Hard to Find
- Each gotcha is documented somewhere, but scattered across GitHub issues, Stack Overflow, and blog posts
- Error messages often don't indicate the root cause
- Some behaviors are undocumented "features"
- The combination of SWA + Functions + Auth creates emergent failure modes
The Gotchas
1. Auth Route Ordering Matters
Symptom: Login callbacks return 401 → infinite redirect loop
Cause: /.auth/* routes must be explicitly allowed for anonymous BEFORE any /* wildcard with authenticated.
Solution:
{
"routes": [
{ "route": "/.auth/*", "allowedRoles": ["anonymous"] },
{ "route": "/*", "allowedRoles": ["authenticated"] }
]
}
Time saved: 1-2 hours
2. Embedded API Overrides Linked Backend
Symptom: Your linked Function App returns 404, but embedded Functions work
Cause: If the workflow has api_location:, SWA deploys embedded Functions which override any linked backend.
Solution: Remove api_location from workflow to route to the linked Function App.
Time saved: 1-2 hours
3. SWA CLI v2.0.8 Silently Fails
Symptom: CLI reports success but nothing uploads
Cause: Known bug in v2.0.8
Solution: Use GitHub Actions (Azure/static-web-apps-deploy@v1) instead.
- uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
app_location: "/"
output_location: "dist"
Time saved: 30-60 min
4. Custom Domain Redirect URIs Required
Symptom: Auth works on default hostname, fails on custom domain
Cause: Entra ID app registration must include callback URIs for BOTH the default SWA hostname AND any custom domain.
Solution: Add both to app registration:
https://yourapp.azurestaticapps.net/.auth/login/aad/callback
https://yourdomain.com/.auth/login/aad/callback
Time saved: 30-60 min
5. Embedded Functions Lack IDENTITY_HEADER
Symptom: ManagedIdentityCredential fails in embedded Functions
Cause: Embedded Functions don't have the managed identity environment variables.
Solution: Create a standalone Function App with system-assigned managed identity, link via az staticwebapp backends link.
az staticwebapp backends link \
--name my-swa \
--resource-group my-rg \
--backend-resource-id /subscriptions/.../Microsoft.Web/sites/my-func-app \
--backend-region eastus
Time saved: 2-3 hours
6. X-Frame-Options Blocks Iframes by Default
Symptom: SWA content won't load in an iframe
Cause: Default X-Frame-Options is DENY.
Solution: Set SAMEORIGIN in staticwebapp.config.json:
{
"globalHeaders": {
"X-Frame-Options": "SAMEORIGIN"
}
}
Time saved: 30 min
7. Vite public/ Requires Rebuild + Redeploy
Symptom: New file in public/ doesn't appear on site
Cause: Files in public/ are copied to dist/ during build. Committing doesn't serve them.
Solution: Rebuild and redeploy:
npm run build
Time saved: 30 min
8. Disconnect Before Switching Deploy Methods
Symptom: Deployment conflicts or stale content
Cause: Previous deployment source still linked
Solution: Disconnect before moving to CLI or new workflow:
az staticwebapp disconnect --name my-swa
Time saved: 30 min
9. Azure Functions v4 Requires Main Entry
Symptom: Functions silently fail to deploy
Cause: package.json must have "main" pointing to the file that registers functions via app.http().
Solution:
{
"main": "dist/index.js"
}
Where index.js contains:
const { app } = require('@azure/functions');
app.http('myFunction', { ... });
Time saved: 1-2 hours
10. Verify Hostname via CLI
Symptom: Using wrong hostname in configuration
Cause: SWA hostnames can change, especially after region changes
Solution: Always verify:
az staticwebapp show --name my-swa --query defaultHostname -o tsv
Time saved: 15 min
11. Self-Host CDN Libraries in Enterprise
Symptom: CDN scripts blocked, CSP violations
Cause: Enterprise environments block external CDNs, tracking prevention enabled
Solution: Self-host all JavaScript libraries in your public/ folder.
Time saved: 1-2 hours + avoids security review
12. AbortController for Streaming Endpoints
Symptom: Long API calls silently drop
Cause: Browsers may kill connections without explicit timeout
Solution:
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 180000);
try {
const response = await fetch(url, { signal: controller.signal });
} finally {
clearTimeout(timeoutId);
}
Time saved: 1-2 hours debugging "random" failures
Evidence
- Issue #4521: Embedded Functions override linked backend
- Issue #892: Auth route ordering
- Project: alex-portfolio (all 12 gotchas encountered)
- Azure Static Web Apps GitHub issues (various)
Related