fix: azd down returns error instead of prompting init steps when no environment exists#6850
fix: azd down returns error instead of prompting init steps when no environment exists#6850
Conversation
Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
…nvironment exists Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
|
/azp run azure-dev - cli |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR updates azd down to avoid triggering interactive environment initialization when no local environments exist, returning an immediate error instead and deferring environment/provisioning resolution until needed.
Changes:
- Switch
downActionto resolve environment and provisioning manager lazily rather than via eager IoC injection. - Add an early
envManager.List()guard inazd downto return a “no environments found” error when.azure/envs are missing. - Add a unit test for the no-environments path and update DI wiring to provide a lazy
*provisioning.Manager.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/cmd/down.go | Adds early “no envs” check; switches to lazy env/provisioning resolution in Run. |
| cli/azd/cmd/container.go | Registers *lazy.Lazy[*provisioning.Manager] as a scoped dependency. |
| cli/azd/cmd/down_test.go | Adds unit test covering the no-environments error path. |
| cli/azd/extensions/microsoft.azd.concurx/go.mod | Module dependency tidy/update (adds/removes indirect deps). |
| cli/azd/extensions/microsoft.azd.concurx/go.sum | Module dependency checksum updates corresponding to go.mod changes. |
| cli/azd/extensions/azure.ai.agents/go.mod | Promotes testify to a direct dependency (used by tests in that module). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| // Get the environment non-interactively (respects -e flag or default environment) | ||
| env, err := a.lazyEnv.GetValue() | ||
| if err != nil { |
There was a problem hiding this comment.
envManager.List() is only used to check for zero environments, but the subsequent lazyEnv.GetValue() can still fail with environment.ErrNameNotSpecified (e.g., when environments exist but no default is set and -e isn’t provided) and the error returned to the user will be unclear ("environment not specified"). Consider using the already-fetched envList to resolve the target environment: if -e is set, validate it exists and return a friendly not-found error; otherwise use the default from envList (or auto-pick when there is exactly one env) and if ambiguous, return an actionable message (e.g., suggest azd env select or azd down -e <name>).
| if err != nil { | |
| if err != nil { | |
| if errors.Is(err, environment.ErrNameNotSpecified) { | |
| // There are environments, but none has been selected or set as default. | |
| // Provide an actionable message instead of a low-context error. | |
| if len(envList) > 1 { | |
| return nil, errors.New( | |
| "no environment selected. Use \"azd env select\" to choose a default environment, or run \"azd down -e <name>\" to target a specific environment", | |
| ) | |
| } | |
| return nil, errors.New( | |
| "no environment selected. Run \"azd env select\" to set a default environment, or \"azd down -e <name>\" to target a specific environment", | |
| ) | |
| } |
|
|
||
| // Get the environment non-interactively (respects -e flag or default environment) | ||
| env, err := a.lazyEnv.GetValue() | ||
| if err != nil { |
There was a problem hiding this comment.
The error path from lazyEnv.GetValue() is returned directly. When the user passes -e for a missing environment, the current error will likely be the low-level "'<name>': environment not found" without guidance. Consider mapping environment.ErrNotFound to a more actionable message (similar to env select / show), e.g., instructing to run azd env list, azd env new, or correct the -e value.
| if err != nil { | |
| if err != nil { | |
| if errors.Is(err, environment.ErrNotFound) { | |
| return nil, fmt.Errorf( | |
| "environment not found. Run \"azd env list\" to see available environments, "+ | |
| "\"azd env new\" to create a new one, or specify a valid environment name with -e", | |
| ) | |
| } |
cli/azd/cmd/down_test.go
Outdated
| return environment.New("test-env"), nil | ||
| }) | ||
|
|
||
| lazyProvisionManager := lazy.NewLazy(func() (*provisioning.Manager, error) { |
There was a problem hiding this comment.
This test validates the no-environments error, but it doesn’t assert that the lazy environment/provisioning resolvers are not invoked (which is the core regression being fixed). Consider wiring lazyEnv / lazyProvisionManager closures to fail the test if called, and add coverage for: (1) -e <missing> returns a clear not-found error, and (2) environments exist but no default is set (ensure down behaves as intended: either selects unambiguously or returns an actionable error).
| return environment.New("test-env"), nil | |
| }) | |
| lazyProvisionManager := lazy.NewLazy(func() (*provisioning.Manager, error) { | |
| require.FailNow(t, "lazyEnv should not be evaluated when no environments exist") | |
| return nil, nil | |
| }) | |
| lazyProvisionManager := lazy.NewLazy(func() (*provisioning.Manager, error) { | |
| require.FailNow(t, "lazyProvisionManager should not be evaluated when no environments exist") |
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
|
@copilot apply changes based on the comments in this thread |
…ceLocator, improve error messages and tests Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
Addressed in 06fa2aa:
Done in commit 06fa2aa:
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot can you revert the go.mod changes in extensions? |
Co-authored-by: JeffreyCA <9157833+JeffreyCA@users.noreply.github.com>
| // Check if there are any environments before proceeding | ||
| envList, err := a.envManager.List(ctx) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("listing environments: %w", err) | ||
| } | ||
| if len(envList) == 0 { | ||
| return nil, errors.New("no environments found. Run \"azd init\" or \"azd env new\" to create one") | ||
| } |

cmd/down.go: remove eager env/provisioning injection, add env check, use lazy env + serviceLocatorcmd/container.go: remove unnecessary lazy provisioning manager registrationcmd/down_test.go: add failServiceLocator helper and tests for error pathsgo.mod/go.sumchanges in extensions (azure.ai.agents,microsoft.azd.concurx)Original prompt
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.