{"record":{"id":"95b8e07bd9e9d985","repo":"microsoft/aspire","slug":"object-reference-not-passed-for-parameter-callback","errorCode":null,"errorMessage":"Object reference not passed for parameter 'callback' (ArgumentNullException: callback)","messagePattern":"Object reference not passed for parameter 'callback' \\(ArgumentNullException: callback\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Rust/RustCargoArgsCallbackAnnotation.cs","lineNumber":31,"sourceCode":"{\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"RustCargoArgsCallbackAnnotation\"/> class.\n    /// </summary>\n    /// <param name=\"callback\">The callback action to be executed.</param>\n    public RustCargoArgsCallbackAnnotation(Action<IList<string>> callback)\n        : this(context =>\n        {\n            callback(context.Args);\n            return Task.CompletedTask;\n        })\n    {\n        ArgumentNullException.ThrowIfNull(callback);\n    }\n\n    /// <summary>\n    /// Gets the callback action that is executed to populate cargo-level arguments.\n    /// </summary>\n    public Func<RustCargoArgsCallbackContext, Task> Callback { get; } = callback ?? throw new ArgumentNullException(nameof(callback));\n}\n\n/// <summary>\n/// Represents callback context for cargo-level command-line arguments.\n/// </summary>\n/// <param name=\"resource\">The Rust application resource whose cargo arguments are being built.</param>\n/// <param name=\"args\">The command-line arguments collection.</param>\n/// <param name=\"cancellationToken\">The cancellation token associated with this callback context.</param>\n/// <remarks>\n/// Unlike program arguments, cargo arguments are plain strings rather than <see cref=\"object\"/>.\n/// They select build behaviour (<c>--release</c>, <c>--features</c>, <c>--bin</c>) before the program\n/// starts, so there is nothing for a deferred value such as an endpoint reference to resolve against;\n/// those belong after the <c>--</c> separator and are added with <c>WithArgs</c>.\n/// </remarks>\npublic sealed class RustCargoArgsCallbackContext(RustAppResource resource, IList<string> args, CancellationToken cancellationToken = default)\n{\n    /// <summary>\n    /// Gets the Rust application resource whose cargo arguments are being built.","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Rust/RustCargoArgsCallbackAnnotation.cs#L13-L49","documentation":"RustCargoArgsCallbackAnnotation's constructor validates its 'callback' parameter with ArgumentNullException.ThrowIfNull and its Callback property initializer repeats the guard. The library requires a non-null delegate because the annotation is invoked later during cargo argument construction; a null callback would crash the pipeline far from the misuse site. The exception names the offending parameter so the mistake is caught at annotation creation time.","triggerScenarios":"Calling new RustCargoArgsCallbackAnnotation(resource, callback, ...) (or the WithCargoArgsCallback-style extension that constructs it) with a null Func<RustCargoArgsCallbackContext, Task>, typically from an uninitialized delegate field or a helper that conditionally assigns the callback.","commonSituations":"Conditional fluent configuration where the callback is only assigned in one branch; a lambda variable that is still null at annotation-creation time; refactoring that removed the lambda but left the call passing the now-null variable.","solutions":["Pass a non-null async lambda when creating the annotation, e.g. args => Task.CompletedTask if no customization is needed","Check any intermediate variable holding the callback for null before constructing the annotation","Move the annotation registration inside the branch where the callback is actually created"],"exampleFix":"// before\nFunc<RustCargoArgsCallbackContext, Task> callback = condition ? ConfigureArgs : null;\nvar annotation = new RustCargoArgsCallbackAnnotation(callback);\n// after\nFunc<RustCargoArgsCallbackContext, Task> callback = condition ? ConfigureArgs : static _ => Task.CompletedTask;\nvar annotation = new RustCargoArgsCallbackAnnotation(callback);","handlingStrategy":"validation","validationCode":"if (callback is null) throw new InvalidOperationException(\"Cargo args callback must be assigned before creating RustCargoArgsCallbackAnnotation.\");","typeGuard":"bool HasCallback(Func<RustCargoArgsCallbackContext, Task>? cb) => cb is not null;","tryCatchPattern":"try { var ann = new RustCargoArgsCallbackAnnotation(cb); } catch (ArgumentNullException ex) when (ex.ParamName == \"callback\") { log.LogError(ex, \"Null cargo args callback\"); }","preventionTips":["Default conditional callbacks to a no-op lambda (static _ => Task.CompletedTask) instead of null","Never store callbacks in nullable fields without a null check at the construction site","Construct annotations inside the branch where the delegate is actually created"],"tags":["argument-null","rust","annotation"],"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"}