{"record":{"id":"2f796222757b10ad","repo":"microsoft/aspire","slug":"the-java-application-resource-name-cannot-be-published","errorCode":null,"errorMessage":"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}'.","messagePattern":"The Java application '(.+?)' 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 '(.+?)'\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Java/JavaDockerfileGenerator.cs","lineNumber":1154,"sourceCode":"\n            return [\"--no-daemon\", .. args];\n        }\n\n        private static (JavaBuildTool Tool, string[] Args) ResolveConfiguredToolAndArgs(JavaAppResource resource, string appDirectory)\n        {\n            // A build step configured with WithMavenBuild/WithGradleBuild states both the tool and the\n            // arguments that produce a deployable artifact, so it is the most precise source.\n            if (resource.TryGetLastAnnotation<JavaBuildStepAnnotation>(out var buildStep))\n            {\n                return (buildStep.Tool, buildStep.Args);\n            }\n\n            if (resource.TryGetLastAnnotation<JavaDetectedBuildToolAnnotation>(out var detected))\n            {\n                var tool = resource.TryGetLastAnnotation<JavaBuildToolAnnotation>(out var launch)\n                    ? launch.Tool\n                    : DetectBuildToolForPublish(resource, appDirectory)\n                        ?? throw new DistributedApplicationException(\n                            $\"The Java application '{resource.Name}' cannot be published because no build tool was found. \" +\n                            $\"Add a pom.xml, build.gradle, build.gradle.kts, settings.gradle, or settings.gradle.kts to '{appDirectory}'.\");\n\n                return (tool, detected.GetConfiguration(tool).BuildArgs);\n            }\n\n            // A launch goal such as spring-boot:run or bootRun identifies the tool but never packages, so\n            // only the tool is taken from it and the packaging arguments are defaulted.\n            if (resource.TryGetLastAnnotation<JavaBuildToolAnnotation>(out var buildTool))\n            {\n                return (buildTool.Tool, DefaultPackageArgs(buildTool.Tool));\n            }\n\n            // Left for an application added with a prebuilt JAR path and no build configuration: the\n            // container still has to produce that JAR, so the tool comes from what is on disk. This uses\n            // the same detector as run mode so publish cannot silently choose Maven for an ambiguous\n            // directory that run mode rejects.\n            if (DetectBuildToolForPublish(resource, appDirectory) is { } detectedTool)","sourceCodeStart":1136,"sourceCodeEnd":1172,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Java/JavaDockerfileGenerator.cs#L1136-L1172","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nbuilder.AddJavaApp(\"api\", \"repo\"); // build files are in repo/server\n// after\nbuilder.AddJavaApp(\"api\", \"repo/server\")\n    .WithMavenBuild();","handlingStrategy":"validation","validationCode":"var dir = \"src/Api\";\nstring[] markers = [\"pom.xml\", \"build.gradle\", \"build.gradle.kts\", \"settings.gradle\", \"settings.gradle.kts\"];\nif (!markers.Any(m => File.Exists(Path.Combine(dir, m))))\n    throw new Exception($\"No Maven/Gradle build file found in {dir}\");","typeGuard":null,"tryCatchPattern":"try { /* publish */ }\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"no build tool was found\"))\n{ /* add build file or call WithMavenBuild/WithGradleBuild */ }","preventionTips":["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"],"tags":["java","build-tool","publish","detection"],"backgroundTag":"missing-required-config","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}