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
- 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.
- Check .gitignore so the wrapper directory (including its .properties and .jar files) is committed.
- 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
- Commit the entire wrapper support directory (.mvn/wrapper or gradle/wrapper), including .properties and .jar files.
- Review .gitignore for patterns that exclude wrapper files.
- Run 'mvn wrapper:wrapper' or 'gradle wrapper' after cloning a repo that ships only the wrapper scripts.
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
- Java application ' ' cannot be published because the…
- Java application ' ' cannot be published because there is…
- Java application ' ' cannot be published because its…
- Java application ' ' has no wrapper at ' '. That path came…
- Java application ' ' has no in ' ' or in the build root…
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)