{"record":{"id":"4f2b317dc3f44d97","repo":"microsoft/aspire","slug":"java-application-resource-name-has-no-wrappername-in","errorCode":null,"errorMessage":"Java application '{resource.Name}' has no {wrapperName} in '{resource.WorkingDirectory}' or in the build root above it. Aspire runs Java applications through the project's own wrapper so that every build uses the tool version the repository pins. Generate one with {GenerateWrapperCommand(tool)}, or point at an existing wrapper with WithWrapperPath.","messagePattern":"Java application '(.+?)' has no (.+?) in '(.+?)' or in the build root above it\\. Aspire runs Java applications through the project's own wrapper so that every build uses the tool version the repository pins\\. Generate one with (.+?), or point at an existing wrapper with WithWrapperPath\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Java/JavaHostingExtensions.cs","lineNumber":1545,"sourceCode":"    {\n        var wrapperPath = JavaBuildToolResolver.ResolveWrapperPath(resource, tool, OperatingSystem.IsWindows());\n\n        if (File.Exists(wrapperPath))\n        {\n            return;\n        }\n\n        if (resource.HasAnnotationOfType<WrapperAnnotation>())\n        {\n            throw new DistributedApplicationException(\n                $\"Java application '{resource.Name}' has no wrapper at '{wrapperPath}'. That path came \" +\n                $\"from {nameof(WithWrapperPath)} and is resolved relative to the application's working \" +\n                $\"directory '{resource.WorkingDirectory}'.\");\n        }\n\n        var wrapperName = JavaBuildToolResolver.GetDefaultWrapperName(tool, OperatingSystem.IsWindows());\n\n        throw new DistributedApplicationException(\n            $\"Java application '{resource.Name}' has no {wrapperName} in '{resource.WorkingDirectory}' \" +\n            $\"or in the build root above it. Aspire runs Java applications through the project's own \" +\n            $\"wrapper so that every build uses the tool version the repository pins. Generate one with \" +\n            $\"{GenerateWrapperCommand(tool)}, or point at an existing wrapper with {nameof(WithWrapperPath)}.\");\n    }\n\n    /// <summary>\n    /// Arranges for the resource's wrapper to be validated once its configuration is final.\n    /// </summary>\n    private static IResourceBuilder<T> WithDeferredWrapperValidation<T>(\n        this IResourceBuilder<T> builder,\n        JavaBuildTool tool) where T : JavaAppResource\n    {\n        // WithMavenGoal and WithMavenBuild both want this, and either may be called more than once, so\n        // the subscription is registered at most once per tool.\n        if (builder.Resource.Annotations.OfType<JavaWrapperValidationAnnotation>().Any(a => a.Tool == tool))\n        {\n            return builder;","sourceCodeStart":1527,"sourceCodeEnd":1563,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Java/JavaHostingExtensions.cs#L1527-L1563","documentation":"Aspire runs Java applications through the project's own wrapper so every build uses the tool version the repository pins. When neither the resource's working directory nor the build root above it contains the default wrapper (mvnw/mvnw.cmd or gradlew/gradlew.bat), and no WithWrapperPath was given, ValidateWrapperExists throws with instructions to generate a wrapper or point at an existing one.","triggerScenarios":"AddJavaApp with a build-tool launch (WithMavenGoal/WithGradleTask or WithMavenBuild/WithGradleBuild) where the project directory lacks the wrapper script; the wrapper exists only in the developer's global installation, not the repo.","commonSituations":"Cloning a repo without wrapper files (gitignored or never committed); on Windows expecting 'gradlew' instead of 'gradlew.bat'; project layout where the wrapper lives in a parent directory outside the searched build root.","solutions":["Generate the wrapper in the project: 'mvn wrapper:wrapper' for Maven or 'gradle wrapper' for Gradle, and commit it","Point at an existing wrapper elsewhere with WithWrapperPath(\"path/to/wrapper\")","Move/copy the wrapper into the resource's working directory or the build root above it"],"exampleFix":"// before\n// project has no mvnw; AppHost: builder.AddJavaApp(\"app\", dir).WithMavenGoal(\"spring-boot:run\")\n// after: run 'mvn wrapper:wrapper' in the project, then\nbuilder.AddJavaApp(\"app\", dir).WithMavenGoal(\"spring-boot:run\"); // mvnw now found","handlingStrategy":"validation","validationCode":"var wrapperName = OperatingSystem.IsWindows() ? \"mvnw.cmd\" : \"mvnw\"; // or gradlew(.bat)\nif (!File.Exists(Path.Combine(workingDirectory, wrapperName)) && !File.Exists(Path.Combine(buildRoot, wrapperName)))\n{\n    // run 'mvn wrapper:wrapper' or 'gradle wrapper' before starting the AppHost\n}","typeGuard":"bool HasWrapper(string dir, string name) => File.Exists(Path.Combine(dir, name));","tryCatchPattern":"try { ConfigureJavaApp(); }\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"has no mvnw\") || ex.Message.Contains(\"has no gradlew\"))\n{\n    // generate the wrapper or point at one via WithWrapperPath\n}","preventionTips":["Commit mvnw/gradlew (and .cmd variants) to every Java project","On Windows ensure gradlew.bat/mvnw.cmd exist, not just the shell scripts","Run 'gradle wrapper' or 'mvn wrapper:wrapper' when creating new Java projects used by Aspire"],"tags":["java","file-not-found","wrapper","maven","gradle"],"backgroundTag":"file-not-found","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"}