TechnitiumSoftware/DnsServer · error · FormatException

No 'healthCheck' was configured for

Error message

No 'healthCheck' was configured for: {appRecordName}

What it means

Thrown by FailoverApp Address.ProcessRequestAsync in the A/AAAA branch when the per-record JSON data has no 'healthCheck' property (or it is empty). FailoverApp needs a named health check to decide which backend address is up, so a record without one is considered malformed and throws FormatException. The name in the message identifies which app record is broken.

Solutions

  1. Open the FailoverApp record named in the message and add a 'healthCheck' key whose value matches a healthCheck defined in the app config.
  2. Confirm the referenced health check exists in the FailoverApp 'healthChecks' section.
  3. If you do not want failover behaviour, remove the A/AAAA record from the FailoverApp zone instead of leaving it half-configured.

Example fix

// before
{ "addresses": ["10.0.0.1","10.0.0.2"] }
// after
{ "healthCheck": "web", "addresses": ["10.0.0.1","10.0.0.2"] }
Defensive patterns

Strategy: validation

Validate before calling

string? hc = jsonAppRecordData.GetPropertyValue("healthCheck", null);
if (string.IsNullOrEmpty(hc))
    throw new ConfigValidationException($"FailoverApp A/AAAA record '{appRecordName}' is missing the required 'healthCheck' field.");

Prevention

When it happens

Trigger: An A/AAAA app record under FailoverApp whose 'data' JSON lacks the 'healthCheck' key, e.g. {"addresses":["1.2.3.4"]} with no healthCheck reference. This branch is only reached for A/AAAA question types that match the record name.

Common situations: Record created from a template that omitted healthCheck, a health check was deleted but the record still references nothing, or a manual JSON edit dropped the field.

Related errors


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

Appendix: source

Thrown at Apps/FailoverApp/Address.cs:177

        public Task<DnsDatagram?> ProcessRequestAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, bool isRecursionAllowed, string zoneName, string appRecordName, uint appRecordTtl, string appRecordData)
        {
            DnsQuestionRecord question = request.Question[0];

            if (!question.Name.Equals(appRecordName, StringComparison.OrdinalIgnoreCase) && !appRecordName.StartsWith('*'))
                return Task.FromResult<DnsDatagram?>(null);

            switch (question.Type)
            {
                case DnsResourceRecordType.A:
                case DnsResourceRecordType.AAAA:
                    {
                        using JsonDocument jsonDocument = JsonDocument.Parse(appRecordData, _jsonParseOptions);
                        JsonElement jsonAppRecordData = jsonDocument.RootElement;

                        string? healthCheck = jsonAppRecordData.GetPropertyValue("healthCheck", null);
                        if (string.IsNullOrEmpty(healthCheck))
                            throw new FormatException("No 'healthCheck' was configured for: " + appRecordName);

                        Uri? healthCheckUrl = null;

                        if (_healthService!.HealthChecks.TryGetValue(healthCheck, out HealthCheck? hc) && ((hc.Type == HealthCheckType.Https) || (hc.Type == HealthCheckType.Http)) && (hc.Url is null))
                        {
                            //read health check url only for http/https type checks and only when app config does not have an url configured
                            if (jsonAppRecordData.TryGetProperty("healthCheckUrl", out JsonElement jsonHealthCheckUrl) && (jsonHealthCheckUrl.ValueKind == JsonValueKind.String))
                            {
                                healthCheckUrl = new Uri(jsonHealthCheckUrl.GetString()!);
                            }
                            else
                            {
                                if (hc.Type == HealthCheckType.Https)
                                    healthCheckUrl = new Uri("https://" + question.Name);
                                else
                                    healthCheckUrl = new Uri("http://" + question.Name);
                            }
                        }

View on GitHub (pinned to d0484b6c1e)