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
- Resolve the source to an absolute path before constructing the annotation, e.g. Path.GetFullPath or Path.Combine(AppContext.BaseDirectory, relative).
- Expand '~' manually — .NET does not expand it; use Environment.GetFolderPath or HOME.
- 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
- Resolve relative and '~' paths with Path.GetFullPath before mounting.
- Anchor relative paths against a known base directory (AppHost project or AppContext.BaseDirectory).
- Beware drive-relative paths on Windows ("C:foo") — always GetFullPath.
- Test mount code on all target OSes since path semantics differ.
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
- Bind mounts must specify a source path.
- Anonymous volumes cannot be read-only.
- AllocatedEndpoint must use the same network as the…
- Cannot set both UseDeveloperCertificate and Certificate…
- Command array cannot be empty.
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)