{"record":{"id":"bec7842cac7a1274","repo":"microsoft/aspire","slug":"argumentnullexception-for-parameter-callback-callback-is-bec784","errorCode":null,"errorMessage":"ArgumentNullException for parameter 'callback' (callback is null).","messagePattern":"ArgumentNullException for parameter 'callback' \\(callback is null\\)\\.","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ApplicationModel/ContainerBuildOptionsCallbackAnnotation.cs","lineNumber":20,"sourceCode":"// The .NET Foundation licenses this file to you under the MIT license.\n\nusing System.Diagnostics.CodeAnalysis;\nusing Aspire.Hosting.Publishing;\nusing Microsoft.Extensions.Logging;\n\nnamespace Aspire.Hosting.ApplicationModel;\n\n/// <summary>\n/// Annotation that provides a callback to configure container build options for a resource.\n/// </summary>\n/// <param name=\"callback\">The callback function to configure container build options.</param>\n[Experimental(\"ASPIREPIPELINES003\", UrlFormat = \"https://aka.ms/aspire/diagnostics/{0}\")]\npublic sealed class ContainerBuildOptionsCallbackAnnotation(Func<ContainerBuildOptionsCallbackContext, Task> callback) : IResourceAnnotation\n{\n    /// <summary>\n    /// Gets the callback function that will be invoked to configure container build options.\n    /// </summary>\n    public Func<ContainerBuildOptionsCallbackContext, Task> Callback { get; } = callback ?? throw new ArgumentNullException(nameof(callback));\n\n    /// <summary>\n    /// Initializes a new instance of <see cref=\"ContainerBuildOptionsCallbackAnnotation\"/> with a synchronous callback.\n    /// </summary>\n    /// <param name=\"callback\">The synchronous callback action to configure container build options.</param>\n    public ContainerBuildOptionsCallbackAnnotation(Action<ContainerBuildOptionsCallbackContext> callback)\n        : this(context =>\n        {\n            callback(context);\n            return Task.CompletedTask;\n        })\n    {\n    }\n}\n\n/// <summary>\n/// Context for configuring container build options via a callback.\n/// </summary>","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ApplicationModel/ContainerBuildOptionsCallbackAnnotation.cs#L2-L38","documentation":"The ContainerBuildOptionsCallbackAnnotation constructor throws ArgumentNullException when the Func<ContainerBuildOptionsCallbackContext, Task> callback is null. The callback is the whole point of the annotation (it configures container build options during pipeline execution), so a null one is always a programming mistake caught at construction.","triggerScenarios":"new ContainerBuildOptionsCallbackAnnotation(null); passing a method group that resolves to null (e.g. a nullable delegate field or a method returning null).","commonSituations":"Building annotations dynamically/reflection-driven code where the callback comes from configuration or an optional parameter left null.","solutions":["Pass a valid callback delegate when constructing the annotation.","If the callback is optional in your code, skip creating the annotation entirely instead of passing null.","Guard upstream inputs: ensure the factory/config supplying the delegate is populated before constructing."],"exampleFix":"// before\nvar annotation = new ContainerBuildOptionsCallbackAnnotation(configuredCallback); // configuredCallback is null\n\n// after\nif (configuredCallback is not null)\n{\n    var annotation = new ContainerBuildOptionsCallbackAnnotation(configuredCallback);\n}","handlingStrategy":"validation","validationCode":"if (callback is null) throw new InvalidOperationException(\"ContainerBuildOptions callback must be provided before creating the annotation.\");","typeGuard":"bool IsValid(ContainerBuildOptionsCallbackAnnotation a) => a.Callback is not null;","tryCatchPattern":"try { new ContainerBuildOptionsCallbackAnnotation(cb); }\ncatch (ArgumentNullException ex) { logger.LogError(ex, \"Callback delegate was null; check factory/config source\"); }","preventionTips":["Never pass nullable delegate fields straight into the constructor; null-check first.","Skip annotation creation entirely when there is nothing to configure.","In factory/config-driven code, validate the delegate resolves before constructing annotations."],"tags":["argument-null","annotation","aspire-pipelines"],"backgroundTag":"null-argument","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"}