DNS check: [DNS_ANSWER] is not a placeholder and undefined placeholders aren't caught at config validation
Description
The type: dns check exposes only [DNS_RCODE] as a condition placeholder, so there is no way to assert that a DNS query actually returned records (as opposed to NOERROR with zero answers / NODATA).
Worse, referencing an undefined placeholder (e.g. [DNS_ANSWER].length > 0) is silently accepted at config-validation time and then silently evaluates to false (measured value 0) on every run — no error, no warning. This is very hard to debug because the config looks valid and [DNS_RCODE] == NOERROR in the same conditions list succeeds, so the endpoint is red for a reason that isn't obvious.
Steps to Reproduce
- Configure a DNS check against a resolver that returns real
Arecords:endpoints: - name: dns-forward url: "10.1.0.2" interval: 1m dns: query-name: google.com query-type: A conditions: - "[DNS_RCODE] == NOERROR" - "[DNS_ANSWER].length > 0" - Start Gatus. Config validation passes — the endpoint is counted (
Validated N endpoints) with no panic and noinvalid conditionerror. - Observe the endpoint result.
[DNS_RCODE] == NOERROR→success=true.[DNS_ANSWER].length > 0→success=false(measured value0) on every check, even though the query returns realArecords.
Expected Behavior
Either:
- A placeholder that exposes the DNS answer and/or answer count, so a user can write
has([DNS_ANSWER]),len([DNS_ANSWER]) > 0, etc.; or - At minimum, config validation should fail fast with a clear
invalid conditionerror when a condition references an undefined placeholder, instead of silently producing a condition that always fails (or, worse, spuriously passes for forms like[DNS_ANSWER] != '').
Actual Behavior
[DNS_ANSWER] is not a recognized placeholder — config/endpoint/placeholder.go defines only DNSRCodePlaceholder = "[DNS_RCODE]". ResolvePlaceholder falls through to return originalPlaceholder, nil for unknown placeholders (to support literal string comparisons), so the condition's left-hand side becomes the literal string [DNS_ANSWER], which numeric comparisons treat as 0 → 0 > 0 is false. No validation error is raised at startup.
Environment
- Gatus version: v5.36.0 (built from source)
- OS: Linux
- Resolver under test: Technitium DNS (though any resolver returning answers reproduces it)
Additional Context
- The resolver does return answers:
dig +short @10.1.0.2 google.com A→ IPv4 addresses. - Source reference:
config/endpoint/placeholder.go— only[DNS_RCODE]is defined for DNS checks; there is no[DNS_ANSWER],[DNS_RESULT], or answer-count placeholder. Unknown placeholders are returned verbatim (line ~189: "Return the original placeholder if we can't resolve it... allows for literal string comparisons"), which silently breaks numeric/len/hasconditions.
Source: TwiN/gatus