TechnitiumSoftware/DnsServer · warning · InvalidOperationException

Failed to delete Secondary node: please try again.

Error message

Failed to delete Secondary node: please try again.

What it means

Thrown as InvalidOperationException when the lock-free swap of the cluster node table fails. DeleteSecondaryNode snapshots _clusterNodes, builds a copy without the target, then publishes it via Interlocked.CompareExchange; if another thread changed _clusterNodes in between, the swap is aborted and you are told to retry. This is a transient optimistic-concurrency conflict, not data corruption.

Source

Thrown at DnsServerCore/Cluster/ClusterManager.cs:794

                throw new DnsServerException("Failed to delete Secondary node: the specified node does not exist in the Cluster.");

            if (secondaryNode.Type == ClusterNodeType.Primary)
                throw new DnsServerException("Failed to delete Secondary node: the specified node is the Cluster Primary node and cannot be deleted.");

            //delete secondary node from cluster nodes
            Dictionary<int, ClusterNode> updatedClusterNodes = new Dictionary<int, ClusterNode>(existingClusterNodes.Count - 1);

            foreach (KeyValuePair<int, ClusterNode> existingClusterNode in existingClusterNodes)
            {
                if (existingClusterNode.Key == secondaryNodeId)
                    continue;

                updatedClusterNodes[existingClusterNode.Key] = existingClusterNode.Value;
            }

            IReadOnlyDictionary<int, ClusterNode> originalValue = Interlocked.CompareExchange(ref _clusterNodes, updatedClusterNodes, existingClusterNodes);
            if (!ReferenceEquals(originalValue, existingClusterNodes))
                throw new InvalidOperationException("Failed to delete Secondary node: please try again.");

            secondaryNode.Dispose();

            //update cluster zone and save zone file
            RemoveClusterPrimaryZoneRecordsFor(secondaryNode);

            //update cluster catalog zone ACLs and save zone file
            UpdateClusterCatalogZoneOptions();

            //save all changes
            SaveConfigFile();

            //notify all secondary nodes
            TriggerNotifyAllSecondaryNodes();

            //trigger NS and SOA update for member zones
            TriggerRecordUpdateForClusterCatalogMemberZones();

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Retry the identical DeleteSecondaryNode call - the snapshot refreshes and the swap should succeed
  2. Serialize cluster-mutation calls behind a single client-side queue/lock
  3. Allow only one outstanding cluster topology change at a time

Example fix

// before
clusterManager.DeleteSecondaryNode(id);

// after
for (int attempt = 0; ; attempt++)
{
    try { clusterManager.DeleteSecondaryNode(id); break; }
    catch (InvalidOperationException ex) when (ex.Message.Contains("please try again") && attempt < 5)
        await Task.Delay(TimeSpan.FromMilliseconds(200 * (attempt + 1)));
}
Defensive patterns

Strategy: retry

Try / catch

catch (InvalidOperationException ex) when (ex.Message.Contains("please try again"))
{
    // transient optimistic-concurrency conflict; retry after brief backoff
}

Prevention

When it happens

Trigger: Two concurrent Delete/Add/Update Secondary calls on the same Primary; a 'remove node' button clicked twice quickly; parallel admin scripts mutating cluster topology.

Common situations: Concurrent cluster mutations under load; a retry storm from an impatient operator; a race between a heartbeat-driven update and an admin delete.

Related errors


AI-assisted analysis of TechnitiumSoftware/DnsServer@d0484b6c1e (2026-08-13). Data as JSON: /api/errors/5de5df02e022b21e. Report an issue: GitHub.