{"record":{"id":"2a696b3b26c9e7eb","repo":"microsoft/aspire","slug":"value-cannot-be-null-parameter-processrunner","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'processRunner')","messagePattern":"Value cannot be null\\. \\(Parameter 'processRunner'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Publishing/ContainerRuntimeBase.cs","lineNumber":29,"sourceCode":"using Aspire.Hosting.ApplicationModel;\nusing Aspire.Hosting.Dcp.Process;\nusing Microsoft.Extensions.Logging;\n\nnamespace Aspire.Hosting.Publishing;\n\n/// <summary>\n/// Base class for container runtime implementations that provides common process execution,\n/// logging, and error handling patterns.\n/// </summary>\ninternal abstract class ContainerRuntimeBase<TLogger> : IContainerRuntime where TLogger : class\n{\n    private readonly ILogger<TLogger> _logger;\n    private readonly IProcessRunner _processRunner;\n\n    protected ContainerRuntimeBase(ILogger<TLogger> logger, IProcessRunner processRunner)\n    {\n        _logger = logger ?? throw new ArgumentNullException(nameof(logger));\n        _processRunner = processRunner ?? throw new ArgumentNullException(nameof(processRunner));\n    }\n\n    /// <summary>\n    /// Gets the logger instance for use in derived classes.\n    /// </summary>\n    protected ILogger<TLogger> Logger => _logger;\n\n    /// <summary>\n    /// Gets the process runner used for container runtime commands.\n    /// </summary>\n    protected IProcessRunner ProcessRunner => _processRunner;\n\n    /// <summary>\n    /// Gets the name of the container runtime executable (e.g., \"docker\", \"podman\").\n    /// </summary>\n    protected abstract string RuntimeExecutable { get; }\n\n    public abstract string Name { get; }","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Publishing/ContainerRuntimeBase.cs#L11-L47","documentation":"The ContainerRuntimeBase protected constructor guards its IProcessRunner dependency with ArgumentNullException. Without a process runner the runtime cannot execute docker/podman commands, so construction is refused.","triggerScenarios":"Constructing a concrete ContainerRuntimeBase subclass passing null for the IProcessRunner parameter.","commonSituations":"IProcessRunner not registered in DI; manual construction in tests passing null; custom subclass hardcoding null instead of forwarding the dependency.","solutions":["Register IProcessRunner in the DI container and resolve it when creating the runtime.","In tests, supply a real ProcessRunner or a hand-written stub implementing IProcessRunner.","Forward the dependency from the subclass constructor instead of passing null."],"exampleFix":"// before\nnew DockerRuntime(logger, null!);\n// after\nservices.AddSingleton<IProcessRunner, ProcessRunner>();\nnew DockerRuntime(logger, services.GetRequiredService<IProcessRunner>());","handlingStrategy":"type-guard","validationCode":"if (processRunner is null) throw new InvalidOperationException(\"ContainerRuntimeBase requires a non-null IProcessRunner\");","typeGuard":"static bool CanCreateRuntime(ILogger<DockerRuntime>? logger, IProcessRunner? runner) => logger is not null && runner is not null;","tryCatchPattern":"try { runtime = new DockerRuntime(logger, processRunner); }\ncatch (ArgumentNullException ex) when (ex.ParamName is \"logger\" or \"processRunner\")\n{\n    processRunner ??= new ProcessRunner(TimeProvider.System, logger!, new DefaultProcessExecutionContextLogger(logger!));\n    runtime = new DockerRuntime(logger!, processRunner);\n}","preventionTips":["Register IProcessRunner as a singleton in the AppHost DI container.","In tests, provide a stub IProcessRunner instead of null.","Constructor-forward dependencies in custom runtime subclasses rather than defaulting to null."],"tags":["dependency-injection","process","constructor"],"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"}