{"record":{"id":"e5fb170423dd3c42","repo":"microsoft/aspire","slug":"value-cannot-be-null-parameter-logger","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'logger')","messagePattern":"Value cannot be null\\. \\(Parameter 'logger'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/ApplicationModel/RequiredCommandValidator.cs","lineNumber":33,"sourceCode":"/// 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,\n        RequiredCommandAnnotation annotation,","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/ApplicationModel/RequiredCommandValidator.cs#L15-L51","documentation":"RequiredCommandValidator logs validation activity and failures through ILogger<RequiredCommandValidator>. Its constructor null-guards the logger, so passing null throws ArgumentNullException with parameter name 'logger'. The logger is required for diagnostics while running and disposing command validation states.","triggerScenarios":"new RequiredCommandValidator(serviceProvider, interactionService, null!) — constructing the validator without a logger; resolving ILogger<RequiredCommandValidator> from a container where logging services were never registered.","commonSituations":"Unit tests that build the validator manually without AddLogging; minimal hosts constructed without logging infrastructure, leaving the typed logger unresolvable and passed as null.","solutions":["Pass a typed logger: sp.GetRequiredService<ILogger<RequiredCommandValidator>>() after registering logging (builder.Services.AddLogging() / AddAspireLogging defaults).","Use NullLogger<RequiredCommandValidator>.Instance when you intentionally want no-op logging (e.g. tests).","Prefer constructing the validator through DI so the logger is injected automatically."],"exampleFix":"// before\nvar validator = new RequiredCommandValidator(sp, interactionService, null!);\n// after\nvar validator = new RequiredCommandValidator(sp, interactionService,\n    sp.GetRequiredService<ILogger<RequiredCommandValidator>>());","handlingStrategy":"validation","validationCode":"if (logger is null)\n{\n    throw new InvalidOperationException(\"Provide ILogger<RequiredCommandValidator>; use NullLogger<T>.Instance for no-op logging.\");\n}","typeGuard":"bool CanBuildValidator(IServiceProvider? sp, IInteractionService? isvc, ILogger? logger) => sp is not null && isvc is not null && logger is not null;","tryCatchPattern":"try\n{\n    var validator = new RequiredCommandValidator(serviceProvider, interactionService, logger);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"logger\")\n{\n    logger = NullLogger<RequiredCommandValidator>.Instance;\n}","preventionTips":["Register logging services (AddLogging) before resolving typed loggers.","Use sp.GetRequiredService<ILogger<T>>() instead of nullable logger fields.","Fall back to NullLogger<T>.Instance in tests or minimal hosts where logging is not configured."],"tags":["null-argument","logging","dependency-injection"],"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"}