microsoft/aspire · error · DistributedApplicationException
Java application ' ' has no wrapper at ' '. That path came…
Error message
Java application '{resource.Name}' has no wrapper at '{wrapperPath}'. That path came from WithWrapperPath and is resolved relative to the application's working directory '{resource.WorkingDirectory}'. What it means
WithWrapperPath let the user point at a custom build-tool wrapper, but the wrapper file does not exist at the given location. ValidateWrapperExists throws a DistributedApplicationException stating that the path came from WithWrapperPath and is resolved relative to the application's working directory.
Solutions
- Fix the path passed to WithWrapperPath so it points at the existing wrapper relative to the resource's working directory
- Move or restore the wrapper script (mvnw/mvnw.cmd or gradlew/gradlew.bat) into the expected location
- Remove WithWrapperPath to fall back to the default wrapper resolution from the working directory or build root
Example fix
// before
.AddJavaApp("app", dir).WithWrapperPath("tools/mvnw") // file not there
// after
.AddJavaApp("app", dir).WithWrapperPath("mvnw") // wrapper sits directly in the working directory Defensive patterns
Strategy: validation
Validate before calling
var wrapperPath = Path.GetFullPath(Path.Combine(workingDirectory, relativeWrapperPath));
if (!File.Exists(wrapperPath))
{
throw new FileNotFoundException($"Wrapper not found at {wrapperPath}; fix the WithWrapperPath argument.");
} Type guard
bool WrapperExists(string workingDir, string relPath) => File.Exists(Path.Combine(workingDir, relPath));
Try / catch
try { ConfigureJavaApp(); }
catch (DistributedApplicationException ex) when (ex.Message.Contains("has no wrapper at"))
{
// fix the WithWrapperPath value or restore the wrapper file
} Prevention
- Pass WithWrapperPath values relative to the resource's working directory
- Commit wrapper scripts to the repository and verify they exist in CI
- Check file existence with File.Exists before configuring a custom wrapper
When it happens
Trigger: Calling WithWrapperPath("some/path/mvnw") where no file exists at workingDirectory/some/path/mvnw; validation runs via WithDetectedBuildTool or deferred wrapper validation.
Common situations: Typo or wrong casing in the wrapper path; passing an absolute path when resolution is relative to WorkingDirectory; the wrapper file was gitignored or not copied into the build context; Windows/macOS path-separator mistakes.
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 ' ' has no in ' ' or in the build root…
- The Java AppHost project in
- Directory ' ' contains both Maven and Gradle build files…
- Java application ' ' cannot be published because its has no…
- Java application ' ' cannot be published because the…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/0b96a63dbf41e296.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Java/JavaHostingExtensions.cs:1537
/// Throws when the wrapper the resource will launch is not on disk.
/// </summary>
/// <remarks>
/// Deferred to resource start so that the whole AppHost has been authored first: only then is it
/// known whether a <see cref="WithWrapperPath{T}(IResourceBuilder{T}, string)"/> override supplied
/// the wrapper that the default location lacks.
/// </remarks>
private static void ValidateWrapperExists(JavaAppResource resource, JavaBuildTool tool)
{
var wrapperPath = JavaBuildToolResolver.ResolveWrapperPath(resource, tool, OperatingSystem.IsWindows());
if (File.Exists(wrapperPath))
{
return;
}
if (resource.HasAnnotationOfType<WrapperAnnotation>())
{
throw new DistributedApplicationException(
$"Java application '{resource.Name}' has no wrapper at '{wrapperPath}'. That path came " +
$"from {nameof(WithWrapperPath)} and is resolved relative to the application's working " +
$"directory '{resource.WorkingDirectory}'.");
}
var wrapperName = JavaBuildToolResolver.GetDefaultWrapperName(tool, OperatingSystem.IsWindows());
throw new DistributedApplicationException(
$"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 {nameof(WithWrapperPath)}.");
}
/// <summary>
/// Arranges for the resource's wrapper to be validated once its configuration is final.
/// </summary>
private static IResourceBuilder<T> WithDeferredWrapperValidation<T>(View on GitHub (pinned to 25830f84bd)