TechnitiumSoftware/DnsServer · error · InvalidDataException

External to internal translation entries must have same addr

Error message

External to internal translation entries must have same address family: {strExternal} - {strInternal}

What it means

SplitHorizonApp's external-to-internal translation maps an external network/address to an internal one. NAT-style translation requires both sides to use the same IP address family (both IPv4 or both IPv6). This InvalidDataException fires when the parsed external and internal NetworkAddress values differ in AddressFamily.

Source

Thrown at Apps/SplitHorizonApp/AddressTranslation.cs:386

                _enabled = jsonGroup.GetProperty("enabled").GetBoolean();
                _translateReverseLookups = jsonGroup.GetProperty("translateReverseLookups").GetBoolean();

                JsonElement jsonExternalToInternalTranslation = jsonGroup.GetProperty("externalToInternalTranslation");

                Dictionary<IPAddress, IPAddress> externalToInternalIpTranslation = new Dictionary<IPAddress, IPAddress>();
                Dictionary<IPAddress, IPAddress> internalToExternalIpTranslation = new Dictionary<IPAddress, IPAddress>();
                List<KeyValuePair<NetworkAddress, NetworkAddress>> externalToInternalNetworkTranslation = new List<KeyValuePair<NetworkAddress, NetworkAddress>>();

                foreach (JsonProperty jsonProperty in jsonExternalToInternalTranslation.EnumerateObject())
                {
                    string strExternal = jsonProperty.Name;
                    string strInternal = jsonProperty.Value.GetString();

                    NetworkAddress external = NetworkAddress.Parse(strExternal);
                    NetworkAddress @internal = NetworkAddress.Parse(strInternal);

                    if (external.AddressFamily != @internal.AddressFamily)
                        throw new InvalidDataException("External to internal translation entries must have same address family: " + strExternal + " - " + strInternal);

                    if (external.PrefixLength != @internal.PrefixLength)
                        throw new InvalidDataException("External to internal translation entries must have same prefix length: " + strExternal + " - " + strInternal);

                    if (
                        ((external.AddressFamily == AddressFamily.InterNetwork) && (external.PrefixLength == 32)) ||
                        ((external.AddressFamily == AddressFamily.InterNetworkV6) && (external.PrefixLength == 128))
                       )
                    {
                        externalToInternalIpTranslation.TryAdd(external.Address, @internal.Address);

                        if (_translateReverseLookups)
                            internalToExternalIpTranslation.TryAdd(@internal.Address, external.Address);
                    }
                    else
                    {
                        externalToInternalNetworkTranslation.Add(new KeyValuePair<NetworkAddress, NetworkAddress>(external, @internal));
                    }

View on GitHub (pinned to d0484b6c1e)

Solutions

  1. Make both the external key and internal value use the same address family.
  2. If translating IPv4 traffic, pair IPv4-with-IPv4; for IPv6, pair IPv6-with-IPv6.
  3. Set up separate translation entries for each family rather than cross-family mappings.

Example fix

// before
"externalToInternalTranslation": {
  "203.0.113.10/32": "fd00::10"
}

// after
"externalToInternalTranslation": {
  "203.0.113.10/32": "10.0.0.10",
  "2001:db8::10/128": "fd00::10"
}
Defensive patterns

Strategy: validation

Validate before calling

using System.Net;
using System.Net.Sockets;

static void AssertSameFamily(string ext, string intl)
{
    var e = IPAddress.TryParse(ext.Split('/')[0], out var ei) ? ei.AddressFamily : throw new InvalidDataException("bad external");
    var i = IPAddress.TryParse(intl.Split('/')[0], out var ii) ? ii.AddressFamily : throw new InvalidDataException("bad internal");
    if (e != i)
        throw new InvalidDataException($"Address family mismatch: {ext} - {intl}");
}

foreach (var (ext, intl) in translationEntries)
    AssertSameFamily(ext, intl);

Try / catch

try { /* load translation config */ }
catch (InvalidDataException ex) when (ex.Message.Contains("same address family"))
{ /* flag the offending entry to the operator */ }

Prevention

When it happens

Trigger: In the 'externalToInternalTranslation' (or equivalent) config object, a property name (external) and its value (internal) parse to different families, e.g. external '203.0.113.0/24' (IPv4) mapped to internal 'fd00::/64' (IPv6).

Common situations: Mixing IPv4 external addresses with IPv6 internal subnets (or vice versa) when configuring 1:1 translation; copy-pasting examples that used a different family than your actual network.

Related errors


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