Skip to content

azd validate (local-preflight): detect immutable resource group location mismatch (P0-1) #9006

Description

@vhvb1989

Parent tracking issue: #9005 (⭐ Priority 0 → P0-1)

Summary

Add a local-preflight validation check (via the extension WithValidationCheck capability) to azure.ai.agents that detects an immutable resource-group region conflict before provisioning starts, and stops azd with a clear note + remediation suggestion instead of a slow, cryptic deploy-time ARM failure.

This is the #1 production error from the top-5 ARM error report (87 operations): a subscription-scoped Bicep deployment fails with InvalidResourceGroupLocation because the target resource group already exists in a different region than AZURE_LOCATION.

Why users hit this (flow)

The extension writes a stable, salted resource-group name (rg-{env}-{salt}) to AZURE_RESOURCE_GROUP at init. Two independent location vars exist:

  • AZURE_LOCATION — resource-group region (immutable once the RG exists)
  • AZURE_AI_DEPLOYMENTS_LOCATION — model/project region (can change independently)

The conflict arises when AZURE_LOCATION is later changed while the salted RG still exists in the original region, e.g.:

  1. Re-running azd ai init when the scope location is empty/unsupported → re-prompt overwrites AZURE_LOCATION to a new region.
  2. Region-list / model-set changes make a prior location "unsupported" → forced re-pick.
  3. --project-id adoption derives the region from the Foundry project (different from the existing RG).
  4. Manual azd env set AZURE_LOCATION <new>.
  5. Confusion between the two location vars.

Because the RG name is stable, the pre-existing RG in the old region collides with the new AZURE_LOCATION, and the subscription-scoped deployment fails at ARM. The region of a resource group cannot be changed, so proceeding is a guaranteed failure — hence the check is a blocking Error (not a proceed-anyway warning).

Proposed check

  • Rule ID: resource_group_location_mismatch
  • CheckType: local-preflight
  • Severity: Error (blocking)
  • Logic (best-effort / non-blocking on lookups):
    • Read AZURE_SUBSCRIPTION_ID, AZURE_LOCATION (prefer ValidationContext.EnvLocation()), AZURE_RESOURCE_GROUP (fallback rg-{env}).
    • If subscription or location empty → skip. LookupTenantAzureDeveloperCLICredential.
    • armresources.ResourceGroupsClient.Get. On 404 (RG not created yet) or any other error → skip silently.
    • If the RG exists and its region differs from AZURE_LOCATION (case-insensitive) → emit a blocking ValidationCheckResult with message + suggestion.
  • Escape hatch: best-effort skip on any resolution/auth/API failure (never blocks validation itself).

Message + suggestion (what the user sees)

Resource group "rg-myenv-abc123" already exists in region "eastus", but AZURE_LOCATION is set to "westus2". A resource group's region cannot be changed, so provisioning would fail with the ARM error "InvalidResourceGroupLocation".

Suggestion (3 remediation paths):

  • Use the existing region: azd env set AZURE_LOCATION eastus
  • Target a different resource group: azd env set AZURE_RESOURCE_GROUP <new-name>
  • Delete the resource group if it is no longer needed: az group delete --name rg-myenv-abc123 --subscription <sub>

Repro steps (verify the check stops azd)

Fast manual repro (forces the conflict without a full first provision):

  1. Create/select an agent project env:
    azd env new rgloc-test
    
  2. Point the env at a subscription and a resource group that exists in one region:
    azd env set AZURE_SUBSCRIPTION_ID <your-sub-id>
    azd env set AZURE_RESOURCE_GROUP rg-rgloc-test
    az group create --name rg-rgloc-test --location eastus --subscription <your-sub-id>
    
  3. Set a conflicting deployment region:
    azd env set AZURE_LOCATION westus2
    
  4. Run provisioning (or azd up). During the validation phase, azd should stop with the message + suggestion above and not attempt the deployment:
    azd provision
    

Expected: azd reports the resource_group_location_mismatch preflight error, prints the 3 remediation options, and aborts before any ARM deployment call.

Natural repro (the real-world flow):

  1. azd ai init + azd up in region eastus (creates rg-{env}-{salt} in eastus).
  2. Change region: azd env set AZURE_LOCATION westus2 (or re-run init and pick a different region).
  3. azd provision → the check stops early with guidance (previously: slow ARM InvalidResourceGroupLocation failure).

Negative cases (should NOT block): RG doesn't exist yet (fresh env), AZURE_LOCATION matches the RG region (incl. different casing), or subscription/location unset.

Implementation

Implemented in the azure.ai.agents extension:

  • internal/project/resource_group_location_check.goResourceGroupLocationCheck implementing azdext.ValidationCheckProvider.
  • Registered in internal/cmd/listen.go via WithValidationCheck({CheckType: "local-preflight", RuleID: "resource_group_location_mismatch", ...}).
  • Unit tests for the pure comparison/message logic.

PR: linked below.

Metadata

Metadata

Assignees

Labels

agenticAgent-related featuresarea/validationInput/config validationext-agentsazure.ai.agents extension

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions