microsoft/aspire · error · DistributedApplicationException

Java application ' ' cannot be published because there is…

Error message

Java application '{resource.Name}' cannot be published because there is no {defaultWrapperName} in '{appDirectory}'. Aspire builds the image with the project's own wrapper so the container uses the tool version the repository pins. Generate one with {JavaHostingExtensions.GenerateWrapperCommand(tool)}, or point at an existing wrapper with WithWrapperPath.

What it means

When no wrapper was explicitly configured, Aspire expects the project's own default wrapper (mvnw or gradlew, non-Windows name) inside the build context directory and throws if it is absent. Aspire deliberately builds the image with the repository-pinned wrapper so the container uses the same tool version the repo pins. The error tells you how to generate the wrapper or override with an existing one.

Solutions

  1. Run the tool's wrapper generation command (JavaHostingExtensions.GenerateWrapperCommand(tool), e.g. 'mvn wrapper:wrapper' or 'gradle wrapper') in the app directory and commit the result.
  2. Call WithWrapperPath to point at an existing wrapper inside the app directory.
  3. Copy an existing mvnw/gradlew (plus .mvn/ or gradle/wrapper supporting files) into the app directory.

Example fix

// before
builder.AddJavaApp("api", "src/Api"); // no mvnw in src/Api
// after
// cd src/Api && mvn wrapper:wrapper
builder.AddJavaApp("api", "src/Api"); // mvnw now present
Defensive patterns

Strategy: validation

Validate before calling

var dir = "src/Api";
if (!File.Exists(Path.Combine(dir, "mvnw")) && !File.Exists(Path.Combine(dir, "gradlew")))
    Console.WriteLine("Generate a wrapper: mvn wrapper:wrapper or gradle wrapper");

Try / catch

try { /* publish */ }
catch (DistributedApplicationException ex) when (ex.Message.Contains("there is no"))
{ /* run mvn wrapper:wrapper / gradle wrapper, then republish */ }

Prevention

When it happens

Trigger: Publishing an AddJavaApp resource without WithWrapperPath where the app directory contains pom.xml/build.gradle but no mvnw/gradlew script (and its sibling files).

Common situations: Fresh Maven/Gradle projects created without 'mvn wrapper:wrapper' or 'gradle wrapper'; wrapper files stripped by .gitignore; template-generated projects that only commit build files; CI checkouts that exclude wrapper jars/scripts.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

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

            {
                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 " +
                    $"{defaultWrapperName} in '{appDirectory}'. Aspire builds the image with the project's " +
                    $"own wrapper so the container uses the tool version the repository pins. Generate one " +
                    $"with {JavaHostingExtensions.GenerateWrapperCommand(tool)}, or point at an existing " +
                    "wrapper with WithWrapperPath.");
            }

            // The build stage is Linux, so a Windows batch wrapper cannot run there even though it is
            // the right choice on the developer's machine. Maven and Gradle ship the POSIX script
            // alongside the batch one under the same base name, so prefer that sibling and only fail
            // when it is genuinely absent.
            // https://maven.apache.org/wrapper/ and https://docs.gradle.org/current/userguide/gradle_wrapper.html
            if (Path.GetExtension(relative) is ".cmd" or ".bat")
            {
                var posixSibling = relative[..^Path.GetExtension(relative).Length];

                if (!File.Exists(Path.Combine(appDirectory, posixSibling.Replace('/', Path.DirectorySeparatorChar))))
                {

View on GitHub (pinned to 25830f84bd)