microsoft/aspire · error · ArgumentNullException

Bind mounts must specify a source path.

Error message

Bind mounts must specify a source path.

What it means

ContainerMountAnnotation represents a mount for a container. Bind mounts map a host path into the container, so a source path is mandatory; a volume mount can be anonymous but a bind mount cannot. When the type is BindMount and source is null or empty, the constructor throws ArgumentNullException naming the source parameter.

Solutions

  1. Pass a non-empty absolute host path as the source for bind mounts.
  2. If the mount has no host source, use ContainerMountType.Volume instead of BindMount.
  3. Guard the source value before constructing the annotation and throw a domain-specific error.

Example fix

// before
var mount = new ContainerMountAnnotation(configHostPath, "/config", ContainerMountType.BindMount, false);
// after
if (string.IsNullOrEmpty(configHostPath)) throw new InvalidOperationException("Config host path must be set for bind mount.");
var mount = new ContainerMountAnnotation(Path.GetFullPath(configHostPath), "/config", ContainerMountType.BindMount, false);
Defensive patterns

Strategy: validation

Validate before calling

if (type == ContainerMountType.BindMount && string.IsNullOrEmpty(source))
    throw new ArgumentException("Bind mounts require a source path.", nameof(source));

Try / catch

try
{
    var mount = new ContainerMountAnnotation(source, target, ContainerMountType.BindMount, isReadOnly);
}
catch (ArgumentNullException ex) when (ex.ParamName == nameof(source))
{
    logger.LogError(ex, "Bind mount to {Target} is missing a host source path", target);
    throw;
}

Prevention

When it happens

Trigger: Calling new ContainerMountAnnotation(null, target, ContainerMountType.BindMount, isReadOnly) or with "" as source — e.g. deriving the host path from a variable that is null at construction time.

Common situations: Mounting a host directory whose path is read from config or an environment variable that is unset; passing a source string built by string interpolation where a segment was empty; copying a volume-mount call and forgetting to switch the type or add a source.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/a2f826767f08d77d. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/ApplicationModel/ContainerMountAnnotation.cs:28

/// Represents a mount annotation for a container resource.
/// </summary>
[DebuggerDisplay("Type = {GetType().Name,nq}, Source = {Source}, Target = {Target}")]
public sealed class ContainerMountAnnotation : IResourceAnnotation
{
    /// <summary>
    /// Instantiates a mount annotation that specifies the details for a container mount.
    /// </summary>
    /// <param name="source">The source path if a bind mount or name if a volume. Can be <c>null</c> if the mount is an anonymous volume.</param>
    /// <param name="target">The target path of the mount.</param>
    /// <param name="type">The type of the mount.</param>
    /// <param name="isReadOnly">A value indicating whether the mount is read-only.</param>
    public ContainerMountAnnotation(string? source, string target, ContainerMountType type, bool isReadOnly)
    {
        if (type == ContainerMountType.BindMount)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException(nameof(source), MessageStrings.ContainerMountBindMountsRequireSourceExceptionMessage);
            }

            if (!Path.IsPathRooted(source))
            {
                throw new ArgumentException(MessageStrings.ContainerMountBindMountsRequireRootedPaths, nameof(source));
            }
        }

        if (type == ContainerMountType.Volume && string.IsNullOrEmpty(source) && isReadOnly)
        {
            throw new ArgumentException(MessageStrings.ContainerMountAnonymousVolumesReadOnlyExceptionMessage, nameof(isReadOnly));
        }

        Source = source;
        Target = target;
        Type = type;
        IsReadOnly = isReadOnly;
    }

View on GitHub (pinned to 25830f84bd)