microsoft/aspire · error · DistributedApplicationException

Java application ' ' cannot be published because its…

Error message

Java application '{resource.Name}' cannot be published because its wrapper '{resolvedWrapperPath}' is outside the build context '{appDirectory}'. Move the wrapper into the application directory, or set the build context to a directory that contains both.

What it means

Aspire's Java Dockerfile generator throws this when the resolved wrapper script (mvnw/gradlew) for a Java app resource resolves outside the Docker build context directory (appDirectory). The Dockerfile must COPY the wrapper from the build context, so a path escaping it (or an absolute path) cannot be expressed. This is a publish-time configuration validation to fail early instead of producing a broken image build.

Solutions

  1. Move the wrapper script (mvnw/gradlew) into the Java application directory used as the build context.
  2. Change the build context (the directory passed to AddJavaApp) so it contains both the app sources and the wrapper.
  3. Point WithWrapperPath at a wrapper that already exists inside the app directory.

Example fix

// before
builder.AddJavaApp("api", "src/Api")
    .WithWrapperPath("../mvnw");
// after
builder.AddJavaApp("api", ".")
    .WithWrapperPath("src/Api/mvnw");
Defensive patterns

Strategy: validation

Validate before calling

var wrapper = "src/Api/mvnw";
var context = "src/Api";
var rel = Path.GetRelativePath(context, wrapper);
if (rel.StartsWith("../") || Path.IsPathRooted(rel))
    throw new Exception("Wrapper must be inside the build context");

Try / catch

try { /* publish */ }
catch (DistributedApplicationException ex) when (ex.Message.Contains("outside the build context"))
{ /* move wrapper or change context, then republish */ }

Prevention

When it happens

Trigger: Calling aspire publish (or generating a Dockerfile) for an AddJavaApp resource whose wrapper — set via WithWrapperPath or the default lookup — resolves to a path outside the app's directory, e.g. '../mvnw' relative path or an absolute path on another root.

Common situations: Pointing WithWrapperPath at a shared wrapper in a parent or sibling repo directory; the app directory being a subfolder of the solution while the wrapper lives at the repo root; Windows absolute wrapper paths mixed with Linux context assumptions.

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/08666d07b36612b5. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Java/JavaDockerfileGenerator.cs:1045

        /// <para>
        /// The wrapper also has to sit inside the build context, because only files under the context are
        /// uploaded to the daemon and reachable by <c>COPY . .</c>. A wrapper outside it exists on the host
        /// and not in the image, so the build would fail partway through with an opaque "not found".
        /// </para>
        /// </remarks>
        /// <exception cref="DistributedApplicationException">No wrapper is present, or the configured wrapper is outside the build context.</exception>
        private static string ResolveWrapperForContext(JavaAppResource resource, string appDirectory, JavaBuildTool tool)
        {
            // Container builds execute on Linux even when publish runs on Windows. Passing that platform
            // to the shared resolver keeps the naming rule identical to run mode without selecting a batch
            // script that the build stage cannot execute.
            var resolvedWrapperPath = JavaBuildToolResolver.ResolveWrapperPath(resource, tool, isWindows: false);
            var isConfigured = resource.HasAnnotationOfType<WrapperAnnotation>();
            var relative = Path.GetRelativePath(appDirectory, resolvedWrapperPath).Replace('\\', '/');

            if (relative.StartsWith("../", StringComparison.Ordinal) || IsPathRootedOnAnyPlatform(relative))
            {
                throw new DistributedApplicationException(
                    $"Java application '{resource.Name}' cannot be published because its wrapper " +
                    $"'{resolvedWrapperPath}' is outside the build context '{appDirectory}'. " +
                    "Move the wrapper into the application directory, or set the build context to a " +
                    "directory that contains both.");
            }

            if (!File.Exists(resolvedWrapperPath))
            {
                if (isConfigured)
                {
                    throw new DistributedApplicationException(
                        $"Java application '{resource.Name}' cannot be published because the wrapper " +
                        $"configured with WithWrapperPath was not found at '{resolvedWrapperPath}'.");
                }

                var defaultWrapperName = JavaBuildToolResolver.GetDefaultWrapperName(tool, isWindows: false);
                throw new DistributedApplicationException(
                    $"Java application '{resource.Name}' cannot be published because there is no " +

View on GitHub (pinned to 25830f84bd)