microsoft/aspire · error · ArgumentOutOfRangeException

ArgumentOutOfRangeException: Specified argument was out of…

Error message

ArgumentOutOfRangeException: Specified argument was out of range of valid values. (Parameter 'tool')

What it means

JavaBuildToolAnnotation.GetConfiguration maps a JavaBuildTool enum to build/launch argument arrays and throws ArgumentOutOfRangeException when the value is neither Maven nor Gradle. This is the annotation layer's guard against an unknown or default(JavaBuildTool) value, since the enum only defines those two tools. It means the annotation was constructed or queried with an unrecognized build tool.

Solutions

  1. Set an explicit JavaBuildTool.Maven or JavaBuildTool.Gradle when configuring the Java resource instead of relying on an uninitialized enum value.
  2. If the value comes from configuration/JSON, validate it against Enum.IsDefined(typeof(JavaBuildTool), value) before casting.
  3. Upgrade the Aspire.Hosting.Java package so the enum and the switch are from the same version.

Example fix

// before
var tool = default(JavaBuildTool);
var (buildArgs, launchArgs) = annotation.GetConfiguration(tool);
// after
var tool = JavaBuildTool.Maven;
var (buildArgs, launchArgs) = annotation.GetConfiguration(tool);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Enum.IsDefined(typeof(JavaBuildTool), tool)) throw new ArgumentException($"Unsupported JavaBuildTool: {tool}");
var (buildArgs, launchArgs) = annotation.GetConfiguration(tool);

Type guard

static bool IsKnownJavaBuildTool(JavaBuildTool tool) => tool is JavaBuildTool.Maven or JavaBuildTool.Gradle;

Try / catch

try { var cfg = annotation.GetConfiguration(tool); } catch (ArgumentOutOfRangeException ex) { log.LogError(ex, "Unknown Java build tool {Tool}", tool); }

Prevention

When it happens

Trigger: Calling GetConfiguration with JavaBuildTool enum value outside {Maven, Gradle}, e.g. default(JavaBuildTool) (which is 0 and not Maven/Gradle if Maven is not 0), a cast of an arbitrary int to JavaBuildTool, or a new enum member added upstream without updating this switch.

Common situations: Deserializing a JavaBuildTool from config or JSON into an out-of-range numeric value; binding resource settings where the tool field was left unset; a newer Aspire version adding a JavaBuildTool member consumed by an older annotation switch (or vice versa).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Hosting.Java/JavaBuildToolAnnotation.cs:78

/// </remarks>
/// <param name="MavenBuildArgs">Arguments that package the application with Maven.</param>
/// <param name="MavenLaunchArgs">Arguments that launch the application with Maven.</param>
/// <param name="GradleBuildArgs">Arguments that package the application with Gradle.</param>
/// <param name="GradleLaunchArgs">Arguments that launch the application with Gradle.</param>
internal sealed record JavaDetectedBuildToolAnnotation(
    string[] MavenBuildArgs,
    string[] MavenLaunchArgs,
    string[] GradleBuildArgs,
    string[] GradleLaunchArgs) : IResourceAnnotation
{
    /// <summary>
    /// Returns the build and launch arguments for <paramref name="tool"/>.
    /// </summary>
    internal (string[] BuildArgs, string[] LaunchArgs) GetConfiguration(JavaBuildTool tool) => tool switch
    {
        JavaBuildTool.Maven => (MavenBuildArgs, MavenLaunchArgs),
        JavaBuildTool.Gradle => (GradleBuildArgs, GradleLaunchArgs),
        _ => throw new ArgumentOutOfRangeException(nameof(tool), tool, null)
    };
}

/// <summary>
/// Records the OpenTelemetry Java agent configured by <c>WithOtelAgent</c>.
/// </summary>
/// <remarks>
/// The environment variable alone is not enough to reproduce the agent in a container. A relative agent
/// path names a file produced by the build, which only exists in the Dockerfile's build stage, so the
/// runtime stage has to copy it forward and the environment variable has to point at where it landed.
/// Without this the published container starts a JVM pointing at an agent JAR that is not in the image
/// and dies during VM initialization.
/// </remarks>
/// <param name="AgentPath">
/// The agent path exactly as authored, before any resolution, or <see langword="null"/> when the caller
/// asked for the location the build tool writes the agent to. That location is resolved on demand rather
/// than when the annotation is added, so <c>WithOtelAgent()</c> and <c>WithMavenBuild()</c> can be called
/// in either order.

View on GitHub (pinned to 25830f84bd)