{"record":{"id":"71c7c711569eb0bf","repo":"microsoft/aspire","slug":"value-cannot-be-null-parameter-interactionservice","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'interactionService')","messagePattern":"Value cannot be null\\. \\(Parameter 'interactionService'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ApplicationModel/RequiredCommandValidator.cs","lineNumber":32,"sourceCode":"/// Default implementation of <see cref=\"IRequiredCommandValidator\"/> that validates commands\n/// are available on the local machine PATH and coalesces validations per command.\n/// </summary>\ninternal sealed class RequiredCommandValidator : IRequiredCommandValidator, IDisposable\n{\n    private readonly IServiceProvider _serviceProvider;\n    private readonly IInteractionService _interactionService;\n    private readonly ILogger<RequiredCommandValidator> _logger;\n\n    // Track validation state per command/callback pair to coalesce notifications and validation work.\n    private readonly ConcurrentDictionary<CommandValidationCacheKey, CommandValidationState> _commandStates = new();\n\n    public RequiredCommandValidator(\n        IServiceProvider serviceProvider,\n        IInteractionService interactionService,\n        ILogger<RequiredCommandValidator> logger)\n    {\n        _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));\n        _interactionService = interactionService ?? throw new ArgumentNullException(nameof(interactionService));\n        _logger = logger ?? throw new ArgumentNullException(nameof(logger));\n    }\n\n    /// <summary>\n    /// Disposes the command validation states, releasing their semaphores.\n    /// </summary>\n    public void Dispose()\n    {\n        foreach (var state in _commandStates.Values)\n        {\n            state.Dispose();\n        }\n        _commandStates.Clear();\n    }\n\n    /// <inheritdoc />\n    public async Task<RequiredCommandValidationResult> ValidateAsync(\n        IResource resource,","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ApplicationModel/RequiredCommandValidator.cs#L14-L50","documentation":"RequiredCommandValidator uses IInteractionService to prompt users when a required command fails validation (e.g. offering to install it). The constructor null-guards this dependency, so a null interactionService throws ArgumentNullException with parameter name 'interactionService'. Without it the validator could not surface validation failures to the dashboard or console.","triggerScenarios":"new RequiredCommandValidator(serviceProvider, null!, logger) — constructing the validator with no interaction service; a DI registration that maps IInteractionService to null (e.g. missing registration resolved with a null default).","commonSituations":"Headless/test hosts that skip registering IInteractionService; manual construction in custom tooling where the interaction service was not yet initialized at validator creation time.","solutions":["Register an interaction service before building the host: builder.Services.AddSingleton<IInteractionService>(new ConsoleInteractionService(...)) or rely on the hosting layer's registration.","Resolve IInteractionService from the service provider rather than passing a field that may be null.","In tests, provide a stub IInteractionService implementation that records/ignores interactions."],"exampleFix":"// before\nvar validator = new RequiredCommandValidator(sp, interactionService!, logger); // interactionService null\n// after\nbuilder.Services.AddSingleton<IInteractionService, ConsoleInteractionService>();\nvar validator = new RequiredCommandValidator(sp, sp.GetRequiredService<IInteractionService>(), logger);","handlingStrategy":"validation","validationCode":"if (interactionService is null)\n{\n    throw new InvalidOperationException(\"Register IInteractionService in DI before constructing RequiredCommandValidator.\");\n}","typeGuard":"bool HasInteractionService(IServiceProvider sp) => sp.GetService<IInteractionService>() is not null;","tryCatchPattern":"try\n{\n    var validator = new RequiredCommandValidator(serviceProvider, interactionService, logger);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"interactionService\")\n{\n    interactionService = serviceProvider.GetRequiredService<IInteractionService>();\n}","preventionTips":["Register IInteractionService (or use the hosting layer's default registration) before building the host.","Resolve the interaction service with GetRequiredService so a missing registration fails loudly with a clearer error.","In test hosts, always provide a stub IInteractionService."],"tags":["null-argument","dependency-injection","interaction"],"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"}