{"record":{"id":"ab5078bc545b0393","repo":"microsoft/aspire","slug":"the-launch-configuration-producer-returns-typeof","errorCode":null,"errorMessage":"The launch configuration producer returns '{typeof(TLaunchConfiguration)}'. An asynchronous producer must bind to an asynchronous {nameof(WithDebugSupport)} overload either by accepting the launch mode and a {nameof(CancellationToken)} or by accepting a {nameof(LaunchConfigurationCallbackContext)}; otherwise the task itself is used as the launch configuration.","messagePattern":"The launch configuration producer returns '(.+?)'\\. An asynchronous producer must bind to an asynchronous (.+?) overload either by accepting the launch mode and a (.+?) or by accepting a (.+?); otherwise the task itself is used as the launch configuration\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ResourceBuilderExtensions.cs","lineNumber":4909,"sourceCode":"    /// later only for executable creations where this debug-support annotation is active, including restarts and replicas.\n    /// The callback does not run for unsupported debug sessions, publish mode, or inactive annotations superseded by\n    /// a later <see cref=\"SupportsDebuggingAnnotation\"/>.\n    /// </remarks>\n    [OverloadResolutionPriority(-1)]\n    [Experimental(\"ASPIREEXTENSION001\", UrlFormat = \"https://aka.ms/aspire/diagnostics/{0}\")]\n    [AspireExportIgnore(Reason = \"Generic debug launch configuration support is not part of the ATS surface.\")]\n    public static IResourceBuilder<T> WithDebugSupport<T, TLaunchConfiguration>(\n        this IResourceBuilder<T> builder,\n        Func<string, TLaunchConfiguration> launchConfigurationProducer,\n        string launchConfigurationType)\n        where T : IResource\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentNullException.ThrowIfNull(launchConfigurationProducer);\n\n        if (typeof(Task).IsAssignableFrom(typeof(TLaunchConfiguration)) || IsValueTask(typeof(TLaunchConfiguration)))\n        {\n            throw new ArgumentException(\n                $\"The launch configuration producer returns '{typeof(TLaunchConfiguration)}'. An asynchronous producer must bind to an asynchronous {nameof(WithDebugSupport)} overload \" +\n                $\"either by accepting the launch mode and a {nameof(CancellationToken)} or by accepting a {nameof(LaunchConfigurationCallbackContext)}; otherwise the task itself is used as the launch configuration.\",\n                nameof(launchConfigurationProducer));\n        }\n\n        return builder.WithDebugSupport(\n            (mode, _) => Task.FromResult(launchConfigurationProducer(mode)),\n            launchConfigurationType);\n\n        static bool IsValueTask(Type type)\n            => type == typeof(ValueTask) || (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTask<>));\n    }\n\n    /// <summary>\n    /// Adds support for asynchronously producing an IDE launch configuration for the resource.\n    /// </summary>\n    /// <typeparam name=\"T\">The resource type.</typeparam>\n    /// <typeparam name=\"TLaunchConfiguration\">The launch configuration type produced for the resource, typically derived from <see cref=\"ExecutableLaunchConfiguration\"/>.</typeparam>","sourceCodeStart":4891,"sourceCodeEnd":4927,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ResourceBuilderExtensions.cs#L4891-L4927","documentation":"This ArgumentException is thrown when a synchronous WithDebugSupport overload is given a producer delegate that returns Task/ValueTask. A sync overload would treat the Task object itself as the launch configuration instead of awaiting it, so the library detects this at registration time and fails fast. The producer must instead bind to the async overload that accepts the launch mode plus a CancellationToken, or one accepting LaunchConfigurationCallbackContext.","triggerScenarios":"Calling builder.WithDebugSupport<TResource, Task<TLaunchConfiguration>>(...) or a ValueTask-returning producer against the synchronous overload of WithDebugSupport, typically by writing an async lambda without choosing the async overload.","commonSituations":"Using C# async lambda syntax that infers Task<T> as the return type while calling the sync overload, or after a refactor changed an overload's signature; common in debug-support/launch-configuration code.","solutions":["Change the producer to the async overload of WithDebugSupport that accepts (launchMode, CancellationToken) or (LaunchConfigurationCallbackContext)","Remove async/await and return the launch configuration synchronously if no async work is needed","Check the generic type arguments: the producer's return type must not be Task or ValueTask for the sync overload"],"exampleFix":"// before\nbuilder.WithDebugSupport(async () => await ProduceLaunchConfigAsync());\n// after\nbuilder.WithDebugSupport(async (launchMode, cancellationToken) =>\n    await ProduceLaunchConfigAsync(launchMode, cancellationToken));","handlingStrategy":"type-guard","validationCode":"if (typeof(Task).IsAssignableFrom(producerType) || producerType == typeof(ValueTask<LaunchConfiguration>) || producerType == typeof(ValueTask))\n    throw new InvalidOperationException(\"Use the async WithDebugSupport overload for Task/ValueTask-returning producers.\");","typeGuard":"bool IsAsyncProducer<TLaunchConfiguration>() => typeof(Task).IsAssignableFrom(typeof(TLaunchConfiguration)) || typeof(TLaunchConfiguration) == typeof(ValueTask);","tryCatchPattern":"try { builder.WithDebugSupport(producer); }\ncatch (ArgumentException ex) when (ex.ParamName == nameof(producer)) { logger.LogError(ex, \"Producer returns Task; use the async overload\"); }","preventionTips":["Match producer signature to overload: async producers need the CancellationToken or LaunchConfigurationCallbackContext overload","Avoid async lambdas when calling the sync overload — let the compiler infer the wrong Task return","Check generic type arguments when chaining WithDebugSupport calls"],"tags":["aspire","async","generics","debugging"],"backgroundTag":"incompatible-source-type","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"}