microsoft/aspire · error · InvalidOperationException

cannot be used when the application is already configured…

Error message

{methodName} cannot be used when the application is already configured to build with {buildStep.Tool}. A Java application is built and launched by a single build tool.

What it means

The build step (WithMavenBuild/WithGradleBuild) and the launch configuration must use the same build tool, because one tool builds and launches the application. WithBuildToolLaunch throws when a JavaBuildStepAnnotation exists for a different tool than the one being configured for launch.

Solutions

  1. Align the build step and launch call to the same tool (e.g. replace WithMavenBuild with WithGradleBuild)
  2. Remove the conflicting build-step call if a single tool should own build and launch
  3. Review the resource's WithMavenBuild/WithGradleBuild and WithMavenGoal/WithGradleTask calls as a pair

Example fix

// before
var java = builder.AddJavaApp("app", dir).WithMavenBuild("package").WithGradleTask("bootRun");
// after
var java = builder.AddJavaApp("app", dir).WithGradleBuild("build").WithGradleTask("bootRun");
Defensive patterns

Strategy: validation

Validate before calling

var hasMavenBuild = builder.Resource.HasAnnotationOfType<JavaBuildStepAnnotation>();
// ensure build-step tool matches the tool you pass to WithGradleTask/WithMavenGoal

Type guard

builder.Resource.TryGetLastAnnotation<JavaBuildStepAnnotation>(out var step) && step.Tool == desiredTool

Try / catch

try { java.WithGradleTask("bootRun"); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already configured to build with"))
{
    // align build step and launch to the same tool
}

Prevention

When it happens

Trigger: Configuring a launch goal with Gradle (WithGradleTask) on a resource whose build step was declared with Maven (WithMavenBuild), or the reverse.

Common situations: Mixing WithMavenBuild with WithGradleTask after copy-pasting from different examples; renaming a project from Maven to Gradle and updating only half of the configuration.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/17023a4353281f8c. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Java/JavaHostingExtensions.cs:707

        // run, so -jar would be ignored. CommunityToolkit rejects both combinations; this port only
        // rejected the Gradle half, letting a Maven+JAR application silently drop its JAR.
        if (builder.Resource.HasAnnotationOfType<JavaJarPathAnnotation>())
        {
            throw new InvalidOperationException(
                $"{methodName} cannot be used when a JAR path has been specified. Use either the " +
                $"{nameof(AddJavaApp)} overload that takes a jarPath, or {methodName}, not both.");
        }

        if (builder.Resource.TryGetLastAnnotation<JavaBuildToolAnnotation>(out var existing) && existing.Tool != tool)
        {
            throw new InvalidOperationException(
                $"{methodName} cannot be used when the application is already configured to launch with " +
                $"{existing.Tool}. A Java application is launched by a single build tool.");
        }

        if (builder.Resource.TryGetLastAnnotation<JavaBuildStepAnnotation>(out var buildStep) && buildStep.Tool != tool)
        {
            throw new InvalidOperationException(
                $"{methodName} cannot be used when the application is already configured to build with " +
                $"{buildStep.Tool}. A Java application is built and launched by a single build tool.");
        }

        builder.WithAnnotation(
            new JavaBuildToolAnnotation(tool, args.Length > 0 ? [goalOrTask, .. args] : [goalOrTask]),
            ResourceAnnotationMutationBehavior.Replace);

        // The launch goal now compiles the application, so the build resource is redundant — unless
        // something outside the launch goal needs the build's output before the application starts.
        if (buildStep is not null
            && builder.ApplicationBuilder.ExecutionContext.IsRunMode
            && !RequiresBuildBeforeLaunch(builder))
        {
            RemoveRunBuildResource(builder, buildStep);
        }

        // Set the command in every execution context. Setting it only in run mode left publish emitting

View on GitHub (pinned to 25830f84bd)