microsoft/aspire · error · InvalidOperationException
Volume source and target must be set
Error message
Volume source and target must be set
What it means
While converting the Aspire resource model to Docker Compose, ProcessVolumes iterates volume/bind-mount definitions and requires both Source and Target to be present. A mount missing either makes the compose volume entry undefined, so it throws InvalidOperationException. Docker Compose cannot express a named/bind volume without both sides.
Solutions
- Provide both source and target in the WithVolume/WithBindMount call, e.g. .WithBindMount("./data", "/app/data").
- If an anonymous volume was intended, use the API variant designed for that instead of passing null source.
- Inspect the resource whose mount is incomplete and fix the null argument at its definition site.
Example fix
// before .WithBindMount(source: null, target: "/app/data") // after .WithBindMount(source: "./data", target: "/app/data");
Defensive patterns
Strategy: validation
Validate before calling
// before publish, assert all mounts are complete
foreach (var m in resource.Annotations.OfType<ContainerMountAnnotation>())
if (m.Source is null || m.Target is null)
throw new InvalidOperationException($"Resource {resource.Name} has a mount missing source or target"); Prevention
- Always pass both source and target to WithVolume/WithBindMount
- Avoid conditional path expressions that can evaluate to null
- Use the anonymous-volume API instead of null sources when auto-generation is wanted
When it happens
Trigger: Publishing to a DockerComposeEnvironment when a resource has a volume/bind mount created with only one side set — e.g. builder.AddX(...).WithVolume(...) or WithBindMount where source path or container target path was passed as null.
Common situations: Anonymous-volume-style calls where developers passed null source expecting auto-generation; string interpolation producing empty/null paths; conditional code paths that skip setting the target.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Bind mounts are not supported by the Kubernetes publisher
- Docker Compose file not found at
- Ensure ' ' is installed and available on PATH.
- Resource ' ' is configured to publish as a Docker Compose…
- Resource ' ' is assigned to compute environment ' ' but…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/3f3ae2c627f25e51.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Docker/DockerComposeEnvironmentContext.cs:81
endpoint.IsExternal,
endpoint.Name));
}
}
private void ProcessVolumes(DockerComposeServiceResource serviceResource)
{
if (!serviceResource.TargetResource.TryGetContainerMounts(out var mounts))
{
return;
}
var bindMountIndex = 0;
foreach (var mount in mounts)
{
if (mount.Source is null || mount.Target is null)
{
throw new InvalidOperationException("Volume source and target must be set");
}
var source = mount.Source;
var name = mount.Source;
// For bind mounts, create environment placeholders for the source path
// Skip the docker socket which should be left as-is for portability
if (mount.Type == ContainerMountType.BindMount && !IsDockerSocket(mount.Source))
{
// Create environment variable name: {RESOURCE_NAME}_BINDMOUNT_{INDEX}
var envVarName = $"{serviceResource.Name.ToUpperInvariant().Replace("-", "_").Replace(".", "_")}_BINDMOUNT_{bindMountIndex}";
bindMountIndex++;
// Add the placeholder to captured environment variables so it gets written to the .env file
// Use the original source path as the default value and pass the ContainerMountAnnotation as the source
var placeholder = environment.AddEnvironmentVariable(
envVarName,
description: $"Bind mount source for {serviceResource.Name}:{mount.Target}",View on GitHub (pinned to 25830f84bd)