{"record":{"id":"11112c85602e6175","repo":"TechnitiumSoftware/DnsServer","slug":"at-least-one-parameter-must-be-provided","errorCode":null,"errorMessage":"At least one parameter must be provided.","messagePattern":"At least one parameter must be provided\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"DnsServerCore.HttpApi/HttpApiClient.cs","lineNumber":295,"sourceCode":"            using JsonDocument jsonDoc = await JsonDocument.ParseAsync(httpResponse.Content.ReadAsStream(cancellationToken), cancellationToken: cancellationToken);\n            JsonElement rootElement = jsonDoc.RootElement;\n\n            CheckResponseStatus(rootElement);\n\n            DashboardStats? stats = rootElement.GetProperty(\"response\").Deserialize<DashboardStats>(_serializerOptions);\n            if (stats is null)\n                throw new HttpApiClientException(\"Invalid JSON response was received.\");\n\n            return stats;\n        }\n\n        public async Task SetClusterSettingsAsync(string actingUsername, IReadOnlyDictionary<string, string> clusterParameters, CancellationToken cancellationToken = default)\n        {\n            if (!_loggedIn)\n                throw new HttpApiClientException(\"No active session exists. Please login and try again.\");\n\n            if (clusterParameters.Count == 0)\n                throw new ArgumentException(\"At least one parameter must be provided.\", nameof(clusterParameters));\n\n            foreach (KeyValuePair<string, string> parameter in clusterParameters)\n            {\n                switch (parameter.Key)\n                {\n                    case \"token\":\n                    case \"node\":\n                        throw new ArgumentException($\"The '{parameter.Key}' is an invalid Settings parameter.\", nameof(clusterParameters));\n                }\n            }\n\n            HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, new Uri(_serverUrl, $\"api/settings/set?actingUser={Uri.EscapeDataString(actingUsername)}\"));\n            httpRequest.Content = new FormUrlEncodedContent(clusterParameters);\n\n            HttpResponseMessage httpResponse = await _httpClient.SendAsync(httpRequest, cancellationToken);\n\n            httpResponse.EnsureSuccessStatusCode();\n","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/TechnitiumSoftware/DnsServer/blob/d0484b6c1e7439cdc53d67d81e9c876cda2ad756/DnsServerCore.HttpApi/HttpApiClient.cs#L277-L313","documentation":"SetClusterSettingsAsync requires a non-empty dictionary of cluster parameters; sending nothing would be a no-op HTTP call. It throws ArgumentException when clusterParameters.Count == 0, before iterating keys or building the request. This is an argument-contract failure, not a server error.","triggerScenarios":"Calling SetClusterSettingsAsync with an empty dictionary, or one that was filtered/cleared before the call.","commonSituations":"Building the parameter map conditionally and passing it through when no conditions matched; a config loader that produced zero entries; refactoring that left the dictionary uninitialized.","solutions":["Populate clusterParameters with at least one valid key/value before calling.","Skip the call entirely when the dictionary is empty rather than passing it.","Add a unit assertion that the dictionary is non-empty in test fixtures."],"exampleFix":"// before\nvar p = new Dictionary<string,string>();\nawait client.SetClusterSettingsAsync(user, p); // throws\n\n// after\nvar p = new Dictionary<string,string> { [\"enableLogging\"] = \"true\" };\nawait client.SetClusterSettingsAsync(user, p);","handlingStrategy":"validation","validationCode":"if (clusterParameters is null || clusterParameters.Count == 0)\n    throw new ArgumentException(\n        \"Provide at least one cluster parameter before calling SetClusterSettingsAsync.\",\n        nameof(clusterParameters));\n\nawait client.SetClusterSettingsAsync(user, clusterParameters);","typeGuard":"static bool HasClusterParams(IReadOnlyDictionary<string, string> p)\n    => p is not null && p.Count > 0;","tryCatchPattern":"catch (ArgumentException ex) when (ex.Message == \"At least one parameter must be provided. (Parameter 'clusterParameters')\")\n{\n    // nothing to send; treat as no-op or surface to caller\n}","preventionTips":["Skip the call when the dictionary is empty rather than passing it.","Populate parameters from a non-empty source before invoking.","Add an assertion in test fixtures that parameters are non-empty."],"tags":["http-api","client","cluster","argument-validation"],"backgroundTag":null,"analyzedSha":"d0484b6c1e7439cdc53d67d81e9c876cda2ad756","analyzedAt":"2026-08-13T22:57:35.508Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}