microsoft / microsoft/aspire

aspire publish --publisher docker-compose crashes with 'Sequence contains more than one matching element'

Open
#17,392 2 comments 0 reactions 0 assignees View on GitHub
area-deployment triage:bot-seen triage:needs-human
Dominant language
C#
Stars
6.3k
Forks
991
Avg merge
2d 15h
Merged PRs (30d)
196

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

Running `aspire publish --publisher docker-compose` on any project with `AddDockerComposeEnvironment` fails with an `InvalidOperationException` because `PrepareDeploymentTargetsAsync` adds duplicate `DeploymentTargetAnnotation` entries to compute resources.

From my investigation, it appears that the `prepare-deployment-targets-{name}` pipeline step executes twice during a publish:

1. Once during `ExecuteStepSequentiallyAsync("before-start", ...)` in `DistributedApplication.StartAsync` (because the step declares `RequiredBySteps = [BeforeStart]` and is included in the transitive dependency closure)
2. Again during the main `ExecuteAsync` DAG execution in `PipelineExecutor`

Both runs share the same `DistributedApplicationModel`, so the second execution adds duplicate annotations to resources that were already annotated in the first pass.

**Note:** I'm not 100% certain this isn't something I'm doing wrong in my AppHost configuration. It's possible there's a setup step I'm missing or a configuration that would prevent the double-execution. However, I've reproduced this with a minimal AppHost that has nothing beyond `AddDockerComposeEnvironment` and a single project resource.

### Expected Behavior

`aspire publish --publisher docker-compose` should complete successfully, producing a `docker-compose.yaml` with all compute resources.

### Steps To Reproduce

Minimal AppHost:

```csharp
var builder = DistributedApplication.CreateBuilder(args);

builder.AddDockerComposeEnvironment("docker-compose")
.WithProperties(env => env.DashboardEnabled = false);

builder.AddProject("api");

builder.Build().Run();
```

Run:
```bash
dotnet run -- publish --publisher docker-compose --output-path ./output
```

### Exceptions (if any)

```
System.InvalidOperationException: Sequence contains more than one matching element
at System.Linq.ThrowHelper.ThrowMoreThanOneMatchException()
at System.Linq.Enumerable.SingleOrDefault[TSource](...)
at Aspire.Hosting.ApplicationModel.ResourceExtensions.GetDeploymentTargetAnnotation(IResource resource, IComputeEnvironment computeEnvironment)
at Aspire.Hosting.Docker.DockerComposeEnvironmentResource.<>c__DisplayClass...(PipelineStepContext context)
```

### .NET Version info

.NET 10.0 (main branch, as of May 2026)

### Anything else?

**Workaround:** Adding an idempotency guard at the top of `PrepareDeploymentTargetsAsync` in `DockerComposeEnvironmentResource.cs` resolves the issue:

```csharp
private bool _deploymentTargetsPrepared;

private async Task PrepareDeploymentTargetsAsync(PipelineStepContext context)
{
if (executionContext.IsRunMode) return;
if (_deploymentTargetsPrepared) return;
_deploymentTargetsPrepared = true;
// ... rest of method
}
```

The issue is in `src/Aspire.Hosting.Docker/DockerComposeEnvironmentResource.cs`, specifically the step registered at line 68-75 which unconditionally adds `DeploymentTargetAnnotation` on each invocation.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.