microsoft/aspire · error · DistributedApplicationException

Java application ' ' cannot be published because its has no…

Error message

Java application '{resource.Name}' cannot be published because its {wrapper} has no '{supportPath}/wrapper/{propertiesName}'. That file pins the build tool version the image is built with. Regenerate the wrapper with {JavaHostingExtensions.GenerateWrapperCommand(tool)} and commit the whole '{supportPath}' directory.

What it means

ResolveWrapperSupportPath requires the wrapper properties file (mvnw wrapper/maven-wrapper.properties or gradle wrapper/gradle-wrapper.properties) to exist in the application directory when publishing with a wrapper. That file pins the build tool version used to build the image; without it the container build would use an unknown tool version, so the generator throws DistributedApplicationException telling you to regenerate the wrapper.

Solutions

  1. Regenerate the wrapper with the documented command (e.g. 'mvn wrapper:wrapper' or 'gradle wrapper') in the application directory and commit the whole wrapper support directory.
  2. Check .gitignore so the wrapper directory (including its .properties and .jar files) is committed.
  3. If you don't need the wrapper, switch the resource configuration to the non-wrapper build tool path.

Example fix

// before: repo contains only ./mvnw (no .mvn/wrapper/maven-wrapper.properties)
// after
cd <app directory>
mvn wrapper:wrapper   # creates .mvn/wrapper/maven-wrapper.properties
git add .mvn && git commit -m "Add Maven wrapper properties"
Defensive patterns

Strategy: validation

Validate before calling

var props = useMaven ? ".mvn/wrapper/maven-wrapper.properties" : "gradle/wrapper/gradle-wrapper.properties";
if (!File.Exists(Path.Combine(appDirectory, props)))
    throw new InvalidOperationException($"Wrapper properties missing: {props}. Run the wrapper generation command and commit the wrapper directory.");

Try / catch

try { await PublishAsync(...); } catch (DistributedApplicationException ex) when (ex.Message.Contains("wrapper")) { Console.Error.WriteLine(ex.Message); return 1; }

Prevention

When it happens

Trigger: Publishing a Java resource configured to use mvnw/gradlew where the application directory lacks '<supportPath>/wrapper/maven-wrapper.properties' (or gradle-wrapper.properties) — e.g. the wrapper was copied incompletely, .mvn/ or gradle/ was gitignored, or the wrapper was never generated.

Common situations: Committing only mvnw/gradlew scripts but not the wrapper/ directory (gitignore patterns like '*.jar' or 'wrapper/' excluding the properties file); creating a fresh repo from scripts only; deleting .mvn or gradle folders during cleanup.

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/2f775cdbd288b441. Report an issue: GitHub.

Appendix: source

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

            // The support directory sits next to the wrapper script, so a wrapper in a subdirectory of the
            // context keeps its own .mvn/gradle directory there rather than at the context root.
            var wrapperDirectory = Path.GetDirectoryName(wrapper.AsSpan());
            var supportPath = wrapperDirectory.IsEmpty
                ? supportDirectoryName
                : $"{wrapperDirectory}/{supportDirectoryName}";

            // Both wrappers store the distribution URL in <support>/wrapper/<tool>-wrapper.properties.
            // https://maven.apache.org/wrapper/ and https://docs.gradle.org/current/userguide/gradle_wrapper.html
            var propertiesName = $"{tool.ToString().ToLowerInvariant()}-wrapper.properties";
            var propertiesPath = Path.Combine(
                appDirectory,
                supportPath.Replace('/', Path.DirectorySeparatorChar),
                "wrapper",
                propertiesName);

            if (!File.Exists(propertiesPath))
            {
                throw new DistributedApplicationException(
                    $"Java application '{resource.Name}' cannot be published because its {wrapper} has no " +
                    $"'{supportPath}/wrapper/{propertiesName}'. That file pins the build tool version the " +
                    $"image is built with. Regenerate the wrapper with " +
                    $"{JavaHostingExtensions.GenerateWrapperCommand(tool)} and commit the whole " +
                    $"'{supportPath}' directory.");
            }

            return supportPath;
        }

        /// <summary>
        /// Resolves the wrapper script as a path relative to the build context.
        /// </summary>
        /// <remarks>
        /// A wrapper is required rather than falling back to a <c>mvn</c>/<c>gradle</c> installed in the
        /// build image: the wrapper pins the tool version in the repository, so the container image is
        /// produced by the same version that built the project locally and in CI.
        /// <para>

View on GitHub (pinned to 25830f84bd)