microsoft/aspire · error · InvalidOperationException

Resource ' ' is already configured to build with . Call…

Error message

Resource '{builder.Resource.Name}' is already configured to build with {existing.Tool}. Call either WithMavenBuild or WithGradleBuild, not both.

What it means

A Java resource can be built by only one tool; building with both would produce two artifacts and the container build would have no way to pick between them. WithJavaBuildStep (backing WithMavenBuild/WithGradleBuild) throws when a JavaBuildStepAnnotation for a different tool already exists.

Solutions

  1. Remove the earlier WithMavenBuild or WithGradleBuild call so only one build tool is configured
  2. Keep only the call matching the project's actual build files (pom.xml vs build.gradle)
  3. Use WithMavenBuild if the project is Maven-based, WithGradleBuild if Gradle-based — not both

Example fix

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

Strategy: validation

Validate before calling

if (builder.Resource.TryGetLastAnnotation<JavaBuildStepAnnotation>(out var existing))
{
    throw new InvalidOperationException("Build step already configured; do not call WithMavenBuild and WithGradleBuild together.");
}

Type guard

builder.Resource.TryGetLastAnnotation<JavaBuildStepAnnotation>(out var existingBuildStep)

Try / catch

try { java.WithGradleBuild("build"); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already configured to build with"))
{
    // remove the earlier WithMavenBuild/WithGradleBuild call
}

Prevention

When it happens

Trigger: Calling WithGradleBuild on a resource that already called WithMavenBuild (or vice versa).

Common situations: Trying to support both Maven and Gradle users by configuring both; switching build systems without removing the old WithMavenBuild/WithGradleBuild call.

Related errors


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

Appendix: source

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

        return builder.WithJavaBuildStep(
            JavaBuildTool.Gradle,
            buildResourceName: $"{builder.Resource.Name}-gradle-build",
            buildArgs: args.Length > 0 ? args : ["clean", "build"]);
    }

    private static IResourceBuilder<T> WithJavaBuildStep<T>(
        this IResourceBuilder<T> builder,
        JavaBuildTool tool,
        string buildResourceName,
        string[] buildArgs)
        where T : JavaAppResource
    {
        // Building with both tools would produce two artifacts and leave the container build with no way
        // to choose between them, so it is rejected the same way conflicting launch modes are.
        if (builder.Resource.TryGetLastAnnotation<JavaBuildStepAnnotation>(out var existing) && existing.Tool != tool)
        {
            throw new InvalidOperationException(
                $"Resource '{builder.Resource.Name}' is already configured to build with {existing.Tool}. " +
                $"Call either WithMavenBuild or WithGradleBuild, not both.");
        }

        if (builder.Resource.TryGetLastAnnotation<JavaBuildToolAnnotation>(out var launchTool) && launchTool.Tool != tool)
        {
            throw new InvalidOperationException(
                $"Resource '{builder.Resource.Name}' is already configured to launch with {launchTool.Tool}. " +
                "A Java application is built and launched by a single build tool.");
        }

        // A launch goal such as spring-boot:run or bootRun compiles the application on its way to running
        // it, so a build resource in front of it would only repeat work. That holds only while the launch
        // goal is what actually starts the application and nothing else needs the build's output first.
        var createRunResource = builder.ApplicationBuilder.ExecutionContext.IsRunMode
            && (RequiresBuildBeforeLaunch(builder)
                || launchTool is null && !builder.Resource.HasAnnotationOfType<JavaDetectedBuildToolAnnotation>());

View on GitHub (pinned to 25830f84bd)