Skip to the content.

Troubleshooting Guide

Solutions for common issues encountered during deployment and operation.

Deployment Issues

Error: “The subscription does not have quota”

Symptoms: Deployment fails with quota-related error message.

Causes:

Solutions:

  1. Try a different region: ```powershell

    List supported regions

    az provider show –namespace Microsoft.Compute ` –query “resourceTypes[?resourceType==’virtualMachines’].locations” -o table

Update parameters.json

“location”: { “value”: “northeurope” }

Retry deployment

.\scripts\Deploy-AvdOccasional.ps1


2. Request quota increase:
   - Go to Azure Portal
   - Navigate to **Quotas** (search bar)
   - Select **Compute** and your region
   - Click quota item and select "+ New Quota Request"
   - Request increase for D2s_v3 VMs (or B2s for light workload)

3. Register required resource providers:
```powershell
az provider register --namespace Microsoft.Compute
az provider register --namespace Microsoft.Network
az provider register --namespace Microsoft.DesktopVirtualization

Error: “InvalidTemplateDeployment” or “ValidationError”

Symptoms: Deployment fails at validation stage with cryptic error message.

Causes:

Solutions:

  1. Validate template locally:
    az deployment group validate `
      --resource-group avd-occasional-rg `
      --template-file infra/main.bicep `
      --parameters @infra/parameters.json `
      -o json | ConvertFrom-Json | .errors
    
  2. Check for Bicep lint errors:
    az bicep build infra/main.bicep
    
  3. Verify parameters.json syntax:
    # Check for JSON errors
    $params = Get-Content infra/parameters.json -Raw | ConvertFrom-Json
    
  4. Check that all resources are available in your region:
    az provider list --query "[?registrationState=='Registered'].namespace" -o tsv
    

Error: “User does not have permissions”

Symptoms: Deployment fails with “Insufficient permissions” or “Unauthorized” error.

Causes:

Solutions:

  1. Verify your role:
    az role assignment list --assignee (az account show --query user.name -o tsv)
    

Output should include Contributor or Owner role.

  1. If insufficient permissions, request access:
    • Contact your subscription owner/administrator
    • Ask for Contributor role assignment on the subscription (not resource group)
    • Verify via above command after access granted
  2. If using Service Principal, ensure it has required permissions:
    # List permissions
    az role assignment list --assignee <service-principal-id>
    

Error: “The template contains invalid syntax”

Symptoms: Bicep build or deployment fails with syntax error.

Causes:

Solutions:

  1. Re-clone repository to get latest correct version:
    rm -Recurse avd-occasional  # Remove local copy
    git clone https://github.com/markheydon/avd-occasional.git
    cd avd-occasional
    
  2. Run Bicep lint to identify issues:
    # Lint all Bicep files
    Get-ChildItem -Recurse -Filter "*.bicep" | ForEach-Object {
     az bicep build $_.FullName
    }
    
  3. Manually inspect parameters.json for malformed JSON:
    • Check for trailing commas
    • Ensure all braces and brackets are balanced
    • Verify string values are quoted with double quotes

Diagnosis with Test-AvdSessionHost

The Test-AvdSessionHost.ps1 script provides automated diagnostics for session host issues. Run it first when troubleshooting connectivity problems:

# Auto-discover and diagnose
.\scripts\Test-AvdSessionHost.ps1

The script checks:

Review the Recommendations section in script output for next steps. Then consult the relevant troubleshooting section below for detailed solutions.


Connection Issues

Error: “Workspace not available in Windows App”

Symptoms: User signs into Windows App but sees no workspaces available.

Causes:

Solutions:

  1. Run diagnostics first:
    .\scripts\Test-AvdSessionHost.ps1
    

    If session host status is “Available”, role assignment may be the issue. Otherwise, see the script output for other problems.

  2. Verify role assignment exists: ```powershell $appGroupId = (az resource list –resource-group avd-occasional-rg ` –resource-type “Microsoft.DesktopVirtualization/applicationGroups” ` –query ‘[0].id’ -o tsv)

az role assignment list –scope $appGroupId –query “[].{Principal:principalName, Role:roleDefinitionName}” -o table


2. If role missing, assign it:
```powershell
$userId = (az ad signed-in-user show --query id -o tsv)
az role assignment create `
  --role "Desktop Virtualization User" `
  --assignee $userId `
  --scope $appGroupId
  1. Wait 5–10 minutes for role to propagate in Azure AD.

  2. Sign out of Windows App completely, then sign back in.

  3. Verify Desktop Application Group exists and is linked to Workspace:

    az desktopvirtualization applicationgroup list `
      --resource-group avd-occasional-rg `
      --query "[].{Name:name, Type:applicationType, WorkspaceName:workspaceName}" -o table
    

Error: “Your account is configured to prevent you from using this device”

Symptoms: User successfully connects to Windows App and sees workspace, but gets error when launching desktop.

Causes:

Solutions:

  1. Run diagnostics first:
    .\scripts\Test-AvdSessionHost.ps1
    

    If session host status is “Available”, review the output:

    • If Power State is “VM deallocated”, start VMs with .\scripts\Start-AvdOccasional.ps1
    • If extensions show errors, redeploy with .\scripts\Deploy-AvdOccasional.ps1
    • If Entra ID auth is missing, check RDP properties and redeploy
    • If heartbeat is old, restart the VM

    If session host is not Available, continue below.

  2. Verify Virtual Machine User Login role is assigned: ```powershell $userId = (az ad signed-in-user show –query id -o tsv) $vmIds = @(az vm list –resource-group avd-occasional-rg –query ‘[].id’ -o tsv)

foreach ($vmId in $vmIds) { $roles = @(az role assignment list –scope $vmId –assignee $userId ` –query “[].roleDefinitionName” -o tsv) if ($roles) { Write-Host “VM $(Split-Path $vmId -Leaf): $($roles -join ‘, ‘)” } else { Write-Host “VM $(Split-Path $vmId -Leaf): NO ROLES ASSIGNED” } }


2. If role missing, assign it:
```powershell
$userId = (az ad signed-in-user show --query id -o tsv)
$vmIds = @(az vm list --resource-group avd-occasional-rg --query '[].id' -o tsv)

foreach ($vmId in $vmIds) {
    az role assignment create `
      --role "Virtual Machine User Login" `
      --assignee $userId `
      --scope $vmId
}
  1. Wait 5–10 minutes for roles to propagate.

  2. Verify VMs are running:

    az vm list --resource-group avd-occasional-rg `
      --query "[].{Name:name, PowerState:powerState}" -o table
    

If stopped, start them:

.\scripts\Start-AvdOccasional.ps1 -WaitForStartup

Error: Cannot Connect to Session Host (Network Timeout)

Symptoms: Connection attempt times out or fails with network unreachable error.

Causes:

Solutions:

  1. Verify VM is running:
    az vm list --resource-group avd-occasional-rg `
      --query "[].{Name:name, PowerState:powerState, ProvisioningState:provisioningState}" -o table
    

Start if needed:

.\scripts\Start-AvdOccasional.ps1 -WaitForStartup
  1. Check Network Security Group rules: ```powershell $nsgId = (az resource list –resource-group avd-occasional-rg ` –resource-type “Microsoft.Network/networkSecurityGroups” ` –query ‘[0].id’ -o tsv)

az network nsg rule list –resource-group avd-occasional-rg ` –nsg-name (Split-Path $nsgId -Leaf) -o table


NSG should allow outbound traffic. If all rules are "Deny", access is blocked.

3. Verify local network connectivity:
   - Temporarily disable personal firewall or VPN
   - Try connecting from a different network (e.g., mobile hotspot)
   - Check if ISP blocks Azure Virtual Desktop traffic

4. Wait a few minutes and try again (Azure Virtual Desktop service may be refreshing).

## VM & Post-Deployment Issues

### VMs Not Appearing or Stuck in "Creating" State

**Symptoms:** Deployment appears to complete, but VMs don't show in resource list or remain stuck in Provisioning state.

**Quick Check:** Run diagnostics:
```powershell
.\scripts\Test-AvdSessionHost.ps1

Review output for extension status and session host registration status.

Causes:

Solutions:

  1. Check VM and extension status via diagnostics:
    .\scripts\Test-AvdSessionHost.ps1
    

    If extensions show failed status, see recommendations in the output.

  2. Check actual deployment status: ```powershell

    Get latest deployment

    $deployment = (az deployment group list –resource-group avd-occasional-rg ` –query ‘[-1]’ | ConvertFrom-Json)

Write-Host “Deployment: $($deployment.name)” Write-Host “State: $($deployment.properties.provisioningState)” Write-Host “Timestamp: $($deployment.properties.timestamp)”

View detailed error (if failed)

if ($deployment.properties.provisioningState -ne ‘Succeeded’) { $deployment.properties.error | ConvertTo-Json }


3. Check VM extension status (Custom Script installation):
```powershell
$vmExtensions = @(az vm extension list --resource-group avd-occasional-rg `
  --vm-name (az vm list --resource-group avd-occasional-rg --query '[0].name' -o tsv) `
  --query "[].{Name:name, ProvisioningState:provisioningState, TypeHandlerVersion:typeHandlerVersion}")

$vmExtensions | ConvertTo-Json

If extension failed, re-run:

.\scripts\Deploy-AvdOccasional.ps1 -WhatIf
  1. Rerun deployment (idempotent safe):
    .\scripts\Deploy-AvdOccasional.ps1
    

High Unexpected Costs

Symptoms: Azure bill significantly higher than £94–126/month (active) or £2–3/month (deallocated).

Causes:

Solutions:

  1. Check VM power states:
    az vm list --resource-group avd-occasional-rg `
      --query "[].{Name:name, PowerState:powerState}" -o table
    

If running, stop them:

.\scripts\Stop-AvdOccasional.ps1
  1. Verify Public IPs are deleted when VMs stopped:
    # Check if Public IPs exist (should be empty when VMs stopped)
    az network public-ip list --resource-group avd-occasional-rg `
      --query "[].{Name:name, IpAddress:ipAddress}" -o table
    

Note: Public IPs are automatically managed by Start/Stop scripts. If IPs remain after stopping, check script executed successfully.

  1. Monitor data egress:
    • Go to Azure Cost Management (Portal)
    • Filter by charge type, resource group
    • Identify which resources generate data costs
    • Reduce file transfers or move data within Azure region
  2. Review for unexpected resources:
    # List all resources by type
    az resource list --resource-group avd-occasional-rg `
      --query "[].{Name:name, Type:type, CostRelevant:type}" -o table
    

Delete any resources created accidentally (databases, additional storage, etc.):

# Example: Delete unexpected database
az resource delete --resource-group avd-occasional-rg --name <resource-name> --resource-type <type>

Script & Automation Issues

PowerShell Execution Policy Error

Symptoms: Script fails with “cannot be loaded because running scripts is disabled on this system”.

Causes: PowerShell execution policy blocks script execution.

Solutions:

  1. Check current policy:
    Get-ExecutionPolicy
    
  2. Temporarily allow scripts for current user/session:
    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
    
  3. Run script:
    .\scripts\Deploy-AvdOccasional.ps1
    
  4. (Optional) Revert execution policy:
    Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope CurrentUser
    

Script Parameter Not Recognised

Symptoms: Running script with -Parameter value results in “Parameter not found” error.

Causes:

Solutions:

  1. Check available parameters:
    Get-Help .\scripts\Deploy-AvdOccasional.ps1 -Parameter *
    
  2. Verify that you’re using a valid parameter name and spelling, matching what Get-Help shows:
    • Example parameter: -AdminPassword
    • PowerShell parameter names are case-insensitive, so -AdminPassword and -adminPassword are treated the same.
  3. Re-clone repository in case script is outdated:
    git clone https://github.com/markheydon/avd-occasional.git
    

General Debugging

Enable Detailed Logging

For deployments, add -Verbose flag:

.\scripts\Deploy-AvdOccasional.ps1 -Verbose

For Azure CLI commands:

az deployment group create ... --debug

Check Azure Activity Log

# Show recent Azure activities
az monitor activity-log list --max-events 20 `
  --query "[].{Time:eventTimestamp, EventName:eventName, Status:status, Message:description}" -o table

Collect Diagnostics

# Export all resource details for debugging
az resource list --resource-group avd-occasional-rg -o json > resources.json

# Export deployment details
az deployment group show --resource-group avd-occasional-rg --name main -o json > deployment.json

Contact Support

If you cannot resolve the issue:

  1. Gather diagnostics:
    • Output of: az account show
    • Output of: az resource list --resource-group avd-occasional-rg
    • Recent error messages (copy full text)
    • Steps already tried
  2. Report issue on GitHub Issues

Next: PowerShell Scripts Reference


Last Updated: February 2026