TechnitiumSoftware/DnsServer · error · ArgumentException
The '{parameter.Key}' is an invalid Settings parameter.
Error message
The '{parameter.Key}' is an invalid Settings parameter. What it means
Thrown by SetClusterSettingsAsync when the clusterParameters dictionary contains the reserved key "token" or "node". These keys are system-managed (authentication token and cluster node identity) and must never be set through the generic api/settings/set endpoint. The client validates input before sending the HTTP request, throwing ArgumentException to fail fast.
Source
Thrown at DnsServerCore.HttpApi/HttpApiClient.cs:303
return stats;
}
public async Task SetClusterSettingsAsync(string actingUsername, IReadOnlyDictionary<string, string> clusterParameters, CancellationToken cancellationToken = default)
{
if (!_loggedIn)
throw new HttpApiClientException("No active session exists. Please login and try again.");
if (clusterParameters.Count == 0)
throw new ArgumentException("At least one parameter must be provided.", nameof(clusterParameters));
foreach (KeyValuePair<string, string> parameter in clusterParameters)
{
switch (parameter.Key)
{
case "token":
case "node":
throw new ArgumentException($"The '{parameter.Key}' is an invalid Settings parameter.", nameof(clusterParameters));
}
}
HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, new Uri(_serverUrl, $"api/settings/set?actingUser={Uri.EscapeDataString(actingUsername)}"));
httpRequest.Content = new FormUrlEncodedContent(clusterParameters);
HttpResponseMessage httpResponse = await _httpClient.SendAsync(httpRequest, cancellationToken);
httpResponse.EnsureSuccessStatusCode();
using JsonDocument jsonDoc = await JsonDocument.ParseAsync(httpResponse.Content.ReadAsStream(cancellationToken), cancellationToken: cancellationToken);
JsonElement rootElement = jsonDoc.RootElement;
CheckResponseStatus(rootElement);
}
public async Task ForceUpdateBlockListsAsync(string actingUsername, CancellationToken cancellationToken = default)
{View on GitHub (pinned to d0484b6c1e)
Solutions
- Remove the "token" and "node" keys from the dictionary before calling SetClusterSettingsAsync.
- Filter the dictionary with a LINQ Where clause that excludes reserved keys.
- Build the dictionary from only user-configurable setting names sourced from the API's own settings schema.
Example fix
// before
var parameters = new Dictionary<string, string>
{
{ "dnsServerPort", "53" },
{ "token", myToken }, // reserved key — causes ArgumentException
{ "node", "primary" } // reserved key — causes ArgumentException
};
await client.SetClusterSettingsAsync(username, parameters, ct);
// after
var reserved = new HashSet<string> { "token", "node" };
var parameters = allSettings
.Where(kv => !reserved.Contains(kv.Key))
.ToDictionary(kv => kv.Key, kv => kv.Value);
await client.SetClusterSettingsAsync(username, parameters, ct); Defensive patterns
Strategy: validation
Validate before calling
// Filter out reserved keys before calling SetClusterSettingsAsync
static readonly HashSet<string> ReservedSettingsKeys = new() { "token", "node" };
Dictionary<string, string> SanitizeSettings(IReadOnlyDictionary<string, string> raw)
{
var violations = raw.Keys.Where(k => ReservedSettingsKeys.Contains(k)).ToList();
if (violations.Count > 0)
throw new ArgumentException($"Reserved settings keys not allowed: {string.Join(", ", violations)}");
return raw.ToDictionary(kv => kv.Key, kv => kv.Value);
}
// usage
var safe = SanitizeSettings(rawSettings);
if (safe.Count > 0)
await client.SetClusterSettingsAsync(username, safe, ct); Type guard
// Predicate to check if a settings dictionary is safe to pass
static bool IsValidSettingsDictionary(IReadOnlyDictionary<string, string> parameters)
{
return parameters.Count > 0
&& !parameters.ContainsKey("token")
&& !parameters.ContainsKey("node");
} Try / catch
try
{
await client.SetClusterSettingsAsync(username, parameters, ct);
}
catch (ArgumentException ex) when (ex.ParamName == "clusterParameters")
{
// a reserved key ("token" or "node") was present
logger.LogWarning("Rejected settings update: {Message}", ex.Message);
} Prevention
- Maintain a constant set of reserved keys ("token", "node") and filter them whenever building a settings dictionary.
- Never round-trip a full raw settings dump — build the update payload from a known-safe schema.
- Unit-test the dictionary construction with both reserved and valid keys to confirm filtering.
When it happens
Trigger: Calling SetClusterSettingsAsync with a dictionary whose keys include "token" or "node", e.g. new Dictionary<string,string>{ {"token", "..."} } or {"node", "..."}.
Common situations: Round-tripping a full settings snapshot back to the server without filtering internal keys; programmatically iterating all server settings and feeding them wholesale into SetClusterSettingsAsync; typos or copy-paste from a raw config dump that includes auth fields.
Related errors
- Ending address must be greater than starting address.
- Lease time in days must be between 0 to 999.
- Lease time in hours must be between 0 to 23.
- Lease time in minutes must be between 0 to 59.
- Server host name cannot exceed 63 bytes.
AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13).
Data as JSON: /api/errors/1833fa0cf8f4863e.
Report an issue: GitHub.