-
-
Notifications
You must be signed in to change notification settings - Fork 7
Understanding Your Diagnosis
You ran netdoc, you have rows and a summary. This page turns that into a next
action.
The single most useful field is the verdict, the summary expressed as one machine-readable word. It answers the question a person on a call-out actually asks: is my network broken, or is theirs?
| Verdict | Meaning | Whose problem |
|---|---|---|
ok |
Every check passed. | Nobody's |
degraded |
Everything you asked for works, but some rung is impaired. | Usually nobody's, yet |
dns |
The name did not resolve. | Resolver / config |
network |
The path is unavailable: link down, no egress, or the target unreachable with nothing else proving the network usable. | Yours (or the path) |
service |
The path works, the far end does not. | Theirs |
incomplete |
A check has no result; the chain did not finish. | Neither, so rerun |
In a --json run this is the verdict field, beside the human summary. In the
TUI it is the sentence under the rows.
The
network/servicesplit is decided by evidence, never by guesswork. An unreachable target is blamed on the service only when direct egress independently succeeded, that is, only when there is proof your network works. With no working egress to compare against, the verdict isnetwork, because accusing a host you never reached would be a guess.
Nothing to do. If you are still seeing a problem, the fault is above the layers
Network Doctor probes: application configuration, authentication, a specific URL
path, or something inside the service. netdoc proved you can reach it and
complete a handshake; it does not log in for you.
Two things worth trying before you conclude that:
- Give it the real target.
netdoc example.comchecks port 443; if your app talks toexample.com:8443, check that. - Run
--watchfor a few minutes. An intermittent fault is invisible in a single green pass.
This is the verdict people most often ignore and should not. It means the
diagnosis found nothing broken for what you asked for, but there is a real
finding sitting beside it. Look for the ! rows.
Common shapes, and what each actually means:
"Online via the environment proxy: direct egress is blocked (proxy-only
network)."
Your machine has no direct route out; the configured HTTPS_PROXY/ALL_PROXY
does. This is normal on many corporate networks. The action is to make sure the
tool that is failing actually honours the proxy environment variables; many do
not.
"…the configured environment proxy check failed, so apps that use the proxy
will fail…"
The mirror image. Direct egress is fine, but your proxy configuration is broken.
Anything that respects HTTPS_PROXY will fail while curl --noproxy '*' works.
Check the proxy variables for a stale host, a dead port, or a NO_PROXY that no
longer covers what it should.
"…the QUIC handshake over UDP/443 failed. Applications can fall back to TCP, which may feel slower." TCP/443 works, UDP/443 does not. Something on the path filters QUIC. Browsers fall back to TCP automatically, so the symptom is slow page starts rather than an outage. Worth reporting to whoever runs the firewall; not worth an incident.
Encrypted DNS unavailable while plaintext DNS works. Ordinary port-53 DNS resolves, but neither DoH nor DoT completed a verified exchange. This is the shape of "my terminal resolves fine but my browser cannot", because modern browsers try encrypted DNS first. The probes can show that one transport worked and the other did not, but not that anybody intended it, so Network Doctor deliberately says no more than this:
"The resolver may be unavailable, or the network may be blocking or interfering with DoH/DoT."
"…system DNS and public DNS disagree; split DNS or filtering may be intentional…" Your resolver and the public second opinion returned different addresses. On a VPN or a corporate network this is usually correct and deliberate (split-horizon DNS). It is reported as a Warn precisely because it is not automatically wrong. It becomes interesting when you did not expect it.
High latency, or one address family down.
internet_tcp reports IPv4 and IPv6 independently, in parallel. ipv6_unreachable
with IPv4 fine is extremely common and usually harmless; it becomes the answer
when the thing you are debugging is IPv6-only.
Look at which DNS rows failed, because they point at different fixes.
| What you see | What it means | What to do |
|---|---|---|
| System DNS fails, public DNS resolves the name | Your configured resolver is failing or filtering. | Check /etc/resolv.conf, your VPN's pushed resolver, a DNS filter or ad-blocker, or a stub resolver that has stopped. |
| Both report no A/AAAA records | The name genuinely has no records. | Check the spelling; check whether the record was actually published. |
| System DNS fails, public DNS unreachable too | Often not really a DNS problem. | Look at the egress rows first, because if there is no egress, DNS failing is a symptom, not the cause. |
That last row is why the verdict logic checks egress before blaming DNS: without working egress, a DNS failure is downstream of the outage.
Drill down with d (dig on Linux/macOS, nslookup on Windows) to see what the
resolver actually said.
Something between you and the target is not carrying traffic. Work down the branches, because they narrow it fast.
Is the interface up? If the Interface row failed, stop here. Nothing else
means anything.
Are you behind a captive portal? This is checked first, ahead of everything else, and for good reason: behind a portal every layer below is answering for the portal, so nothing further down the stack means what it says. The summary says so before it says anything else:
"Behind a captive portal: traffic is intercepted until you sign in to the network."
Sign in first and rerun. The row includes the sign-in URL when the response supplied a valid one (the app displays it but never opens it).
Is direct egress dead but the proxy alive? Then it is a proxy-only network;
see degraded above.
Is nothing reachable at all? The summary is:
"…neither it nor the general internet is reachable: local egress problem."
Look at your default route (i in the toolbox), your gateway, and your Wi-Fi
association.
Does TCP connect and then everything stalls? Check the Path MTU row. If it warns that a 24 KiB write went unacknowledged and a protocol check timed out, the verdict names a probable MTU black hole. This is the tunnel/VPN/PPPoE fault described in How Network Doctor Works. The fix is almost always to lower the MSS or MTU on the tunnel interface, and the row suggests the experiment.
On Linux, a failed direct-egress row may carry a structured cause that names the
kernel-level reason: no_default_route, gateway_unreachable,
selected_path_failed, or preferred_route_failed. Those are visible in --json
under cause.
This is the verdict that lets you stop debugging your own machine. The general internet was independently proven reachable, and this specific target still is not working.
| Row that failed | What it means | Likely cause |
|---|---|---|
| TCP | DNS resolved and the internet works, but the port does not answer. | Remote port closed, remote firewall, or VPN routing that does not cover this destination. |
| TLS | TCP connects, the handshake does not. | Expired or not-yet-valid certificate, hostname mismatch, untrusted issuer, clock skew, or a MITM proxy. |
| HTTPS | TLS is fine, no HTTP response. | Application-layer block, or a proxy sitting in front. |
| HTTP (on a TLS target) | HTTPS works but the plain :80 endpoint does not. |
The redirect endpoint is blocked or not served. Often harmless. |
| SSH / SMTP banner | TCP is accepted, the banner check failed. | Service not actually running on that port, or refusing before it speaks. |
A Warn on a banner row is not a failure:
"…accepts TCP but sent no service banner."
Some services legitimately wait for the client to speak first.
For TLS specifically, --json gives you a stable cause so you do not have to
parse prose: certificate_expired, certificate_not_yet_valid,
hostname_mismatch, untrusted_issuer, tls_handshake_failure,
tcp_unreachable, timeout, connection_closed. The full list of causes across
every probe is in the README's
JSON output
section.
A probe has no result. You quit before it finished, or the run was interrupted.
Rerun it. If it happens repeatedly, that is worth an issue; include a --json
run.
Both of these are "I cannot reach the service." They have opposite fixes.
Case A
✓ Interface using wlan0 …
✓ Internet (TCP egress)
✓ DNS api.example.com → 203.0.113.10
✗ TCP api.example.com:443
Direct egress passed. So the network demonstrably works, and this one host does
not answer. Verdict: service, from:
"…is unreachable though DNS and the general internet work: remote port closed, firewall, or VPN routing."
Stop debugging your laptop; go ask whoever runs the service, or check whether your VPN covers that subnet.
Case B
✓ Interface using wlan0 …
✗ Internet (TCP egress)
✓ DNS api.example.com → 203.0.113.10
✗ TCP api.example.com:443
Egress failed too. The name resolved (a cached or local answer will do that), but
nothing is reachable. Verdict: network, from:
"…resolves but neither it nor the general internet is reachable: local egress problem."
Network Doctor deliberately does not say the service is down, because it never got far enough to know.
The only difference between the two is one independent row. That is the whole reason the egress branch does not depend on DNS.
A verdict is a conclusion; the drill-down tools give you the artefact. Press the
hotkey for the tool you would have reached for anyway: t for traceroute, c
for curl (or a protocol-appropriate handshake probe on SSH/SMTP targets), m
for mtr/pathping, i for the route table, s for sockets. Jobs stream, run
concurrently, and tab switches between them.
y / w copy or save a reviewable report of the whole chain plus every tool job.
Review it before sharing. Tool evidence may contain internal hostnames, addresses, usernames, and interface names.
- How Network Doctor Works: why the rows are arranged this way.
- Troubleshooting and FAQ: rows that behave in surprising ways.
- Challenge Mode: practise this on faults with known answers.
This wiki is the explanatory half of Network Doctor's documentation. Exact
flags, defaults, exit codes, and inventories are authoritative in the
repository and in each command's
own --help; see Documentation Map. Where the two
disagree, the repository is right.
Using netdoc
Using netdoc-sim
Contributing
Authoritative docs