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
A records:
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 no invalid condition error.
- Observe the endpoint result.
[DNS_RCODE] == NOERROR → success=true. [DNS_ANSWER].length > 0 → success=false (measured value 0) on every check, even though the query returns real A records.
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 condition error 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/has conditions.
Description
The
type: dnscheck exposes only[DNS_RCODE]as a condition placeholder, so there is no way to assert that a DNS query actually returned records (as opposed toNOERRORwith 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 tofalse(measured value0) on every run — no error, no warning. This is very hard to debug because the config looks valid and[DNS_RCODE] == NOERRORin the same conditions list succeeds, so the endpoint is red for a reason that isn't obvious.Steps to Reproduce
Arecords:Validated N endpoints) with no panic and noinvalid conditionerror.[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:
has([DNS_ANSWER]),len([DNS_ANSWER]) > 0, etc.; orinvalid 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.godefines onlyDNSRCodePlaceholder = "[DNS_RCODE]".ResolvePlaceholderfalls through toreturn originalPlaceholder, nilfor unknown placeholders (to support literal string comparisons), so the condition's left-hand side becomes the literal string[DNS_ANSWER], which numeric comparisons treat as0→0 > 0isfalse. No validation error is raised at startup.Environment
Additional Context
dig +short @10.1.0.2 google.com A→ IPv4 addresses.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.