microsoft/aspire · error · ArgumentException

Bind mounts must specify an absolute path.

Error message

Bind mounts must specify an absolute path.

What it means

For bind mounts the source must be an absolute (rooted) path, because the host path is passed directly to the container runtime and relative paths are ambiguous. If the type is BindMount and Path.IsPathRooted(source) is false, the constructor throws ArgumentException (MessageStrings.ContainerMountBindMountsRequireRootedPaths) on the source parameter.

Solutions

  1. Resolve the source to an absolute path before constructing the annotation, e.g. Path.GetFullPath or Path.Combine(AppContext.BaseDirectory, relative).
  2. Expand '~' manually — .NET does not expand it; use Environment.GetFolderPath or HOME.
  3. If a relative/anonymous mount is intended, use ContainerMountType.Volume instead.

Example fix

// before
var mount = new ContainerMountAnnotation("./data", "/data", ContainerMountType.BindMount, false);
// after
var hostPath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "data"));
var mount = new ContainerMountAnnotation(hostPath, "/data", ContainerMountType.BindMount, false);
Defensive patterns

Strategy: validation

Validate before calling

var fullSource = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, relative));
if (type == ContainerMountType.BindMount && !Path.IsPathRooted(fullSource))
    throw new ArgumentException($"Bind mount source must be rooted: '{source}'", nameof(source));

Try / catch

try
{
    var mount = new ContainerMountAnnotation(source, target, ContainerMountType.BindMount, false);
}
catch (ArgumentException ex) when (ex.ParamName == nameof(source))
{
    logger.LogError(ex, "Bind mount source '{Source}' is not an absolute path", source);
    throw new InvalidOperationException("Resolve the bind mount source to an absolute path.", ex);
}

Prevention

When it happens

Trigger: new ContainerMountAnnotation("data", "/data", ContainerMountType.BindMount, false) or any relative path such as "./data", "~/data", or a path built by joining without Path.GetFullPath/Root.

Common situations: Using '~' paths (not expanded by .NET on all platforms); paths relative to the AppHost project that were never resolved; code working locally with absolute paths but failing in CI where a variable holds a relative path; drive-relative Windows paths like "C:data".

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

    /// <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;
    }

    /// <summary>
    /// Gets the source of the bind mount or name if a volume. Can be <c>null</c> if the mount is an anonymous volume.
    /// </summary>
    public string? Source { get; }

View on GitHub (pinned to 25830f84bd)