microsoft/aspire · error · DistributedApplicationException
The Java application
Error message
The Java application '{resource.Name}' cannot be published because no build tool was found. Add a pom.xml, build.gradle, build.gradle.kts, settings.gradle, or settings.gradle.kts to '{appDirectory}'. What it means
During publish, Aspire must know whether Maven or Gradle builds the deployable JAR, but no build tool was detected: the JavaBuildToolAnnotation was absent and no pom.xml/gradle build or settings file exists in the app directory. The publish pipeline cannot generate a Dockerfile without knowing the build tool, so it fails with instructions on which marker files it looks for.
Solutions
- Add a pom.xml or Gradle build/settings file to the app directory (or point AddJavaApp at the directory that has one).
- Call WithMavenBuild or WithGradleBuild to explicitly state the build tool.
- Verify appDirectory points at the project root containing the build file.
Example fix
// before
builder.AddJavaApp("api", "repo"); // build files are in repo/server
// after
builder.AddJavaApp("api", "repo/server")
.WithMavenBuild(); Defensive patterns
Strategy: validation
Validate before calling
var dir = "src/Api";
string[] markers = ["pom.xml", "build.gradle", "build.gradle.kts", "settings.gradle", "settings.gradle.kts"];
if (!markers.Any(m => File.Exists(Path.Combine(dir, m))))
throw new Exception($"No Maven/Gradle build file found in {dir}"); Try / catch
try { /* publish */ }
catch (DistributedApplicationException ex) when (ex.Message.Contains("no build tool was found"))
{ /* add build file or call WithMavenBuild/WithGradleBuild */ } Prevention
- Ensure AddJavaApp points at the directory containing pom.xml or gradle files
- Call WithMavenBuild/WithGradleBuild explicitly when layout is nonstandard
- For multi-module repos, target the module directory, not the repo root
When it happens
Trigger: Publishing an AddJavaApp resource where the app directory contains none of pom.xml, build.gradle, build.gradle.kts, settings.gradle, settings.gradle.kts, and no explicit WithMavenBuild/WithGradleBuild (JavaBuildToolAnnotation) was applied.
Common situations: Pointing AddJavaApp at the wrong directory (parent or sibling of the actual project); non-standard multi-module layout where build files live in a subdirectory; apps built with a different tool (Ant, Bazel); directory containing only source code.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- The Java application
- Directory ' ' contains no pom.xml, build.gradle…
- ArgumentOutOfRangeException: Specified argument was out of…
- Directory ' ' contains both Maven and Gradle build files…
- Java application ' ' cannot be published because its…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/2f796222757b10ad.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Java/JavaDockerfileGenerator.cs:1154
return ["--no-daemon", .. args];
}
private static (JavaBuildTool Tool, string[] Args) ResolveConfiguredToolAndArgs(JavaAppResource resource, string appDirectory)
{
// A build step configured with WithMavenBuild/WithGradleBuild states both the tool and the
// arguments that produce a deployable artifact, so it is the most precise source.
if (resource.TryGetLastAnnotation<JavaBuildStepAnnotation>(out var buildStep))
{
return (buildStep.Tool, buildStep.Args);
}
if (resource.TryGetLastAnnotation<JavaDetectedBuildToolAnnotation>(out var detected))
{
var tool = resource.TryGetLastAnnotation<JavaBuildToolAnnotation>(out var launch)
? launch.Tool
: DetectBuildToolForPublish(resource, appDirectory)
?? throw new DistributedApplicationException(
$"The Java application '{resource.Name}' cannot be published because no build tool was found. " +
$"Add a pom.xml, build.gradle, build.gradle.kts, settings.gradle, or settings.gradle.kts to '{appDirectory}'.");
return (tool, detected.GetConfiguration(tool).BuildArgs);
}
// A launch goal such as spring-boot:run or bootRun identifies the tool but never packages, so
// only the tool is taken from it and the packaging arguments are defaulted.
if (resource.TryGetLastAnnotation<JavaBuildToolAnnotation>(out var buildTool))
{
return (buildTool.Tool, DefaultPackageArgs(buildTool.Tool));
}
// Left for an application added with a prebuilt JAR path and no build configuration: the
// container still has to produce that JAR, so the tool comes from what is on disk. This uses
// the same detector as run mode so publish cannot silently choose Maven for an ambiguous
// directory that run mode rejects.
if (DetectBuildToolForPublish(resource, appDirectory) is { } detectedTool)View on GitHub (pinned to 25830f84bd)