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}', or call WithMavenBuild or WithGradleBuild to state how the deployable JAR is produced. What it means
In the no-detected-build-tool-annotation path, publish tries configured tool, then filesystem detection; if neither yields a tool it throws with an expanded message that also suggests WithMavenBuild/WithGradleBuild. Like error 995, publish cannot proceed without knowing how to produce the deployable JAR.
Solutions
- Call WithMavenBuild or WithGradleBuild on the resource to declare the build tool explicitly.
- Add a pom.xml or Gradle build/settings file to the directory given to AddJavaApp.
- Point AddJavaApp at the directory that actually contains the build file.
Example fix
// before
builder.AddJavaApp("api", "src/api"); // no pom.xml or gradle files
// after
builder.AddJavaApp("api", "src/api")
.WithGradleBuild(); // or add build.gradle.kts to src/api 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))))
resourceBuilder.WithGradleBuild(); // declare the tool explicitly Try / catch
try { /* publish */ }
catch (DistributedApplicationException ex) when (ex.Message.Contains("WithMavenBuild or WithGradleBuild"))
{ /* declare the build tool explicitly and republish */ } Prevention
- Prefer explicit WithMavenBuild/WithGradleBuild in publish-focused apps
- Standardize on Maven or Gradle marker files in every Java module
- Validate app directory contents in CI before publishing
When it happens
Trigger: Publishing an AddJavaApp resource with no JavaDetectedBuildToolAnnotation source path leading to a tool: no build-tool annotation from run mode and DetectBuildToolForPublish finds no pom.xml/gradle files in appDirectory.
Common situations: Same as 995: wrong directory, build files elsewhere, exotic build setups; also resources created via paths that never ran run-mode detection.
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/eaed38656d57dc41.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Java/JavaDockerfileGenerator.cs:1177
}
// 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)
{
return (detectedTool, DefaultPackageArgs(detectedTool));
}
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}', " +
"or call WithMavenBuild or WithGradleBuild " +
"to state how the deployable JAR is produced.");
}
private static string[] DefaultPackageArgs(JavaBuildTool tool) => tool switch
{
// -B disables the ANSI progress output that renders as noise in a build log, and -ntp drops
// the per-artifact download lines. Tests are skipped because the container build produces a
// deployable artifact; running the test suite belongs to CI, not to `aspire publish`.
JavaBuildTool.Maven => ["-B", "-ntp", "-DskipTests", "package"],
JavaBuildTool.Gradle => ["-x", "test", "build"],
_ => throw new UnreachableException()
};
/// <summary>
/// Emits a shell command that resolves <paramref name="outputGlob"/> to exactly one JAR and copiesView on GitHub (pinned to 25830f84bd)