Skip to content

fix(config-health): test via the domain, explain errors, notify - #87

Merged
hiddify-com merged 2 commits into
hiddify:devfrom
Hiddify-Official:fix/config-health
Oct 23, 2026
Merged

hiddify-com merged 2 commits into
hiddify:devfrom
Hiddify-Official:fix/config-health

Conversation

@Hiddify-Official

Copy link
Copy Markdown
Contributor

Builds on #86 (the notifications bell) and includes its commit until that one is merged. Only the last commit is this fix.

Problem

Config health on the dashboard could fail with a raw error that overflowed the card: Could not fetch the subscription: HTTPSConnectionPool(...) SSLError(CertificateError("hostname '<ip>' doesn't match ...")). It didn't say what was wrong or where to look.
Root cause: the check fetched the subscription from the first domain, which can be the server's bare IP. The server's certificate is for its name, not that IP, so the fetch failed although the configs were fine.

Change

  • Address (proxy_v3/config_health.py, config_tester.py):
    • a domain name is preferred over a bare IP;
    • with only an IP, the server fetches its own subscription without the certificate check (fetch(verify=False)), since no certificate names a bare IP.
  • Errors (config_health.py):
    • each error gets a kind: certificate, timeout, dns, unreachable, http, empty, core, other;
    • the stored message no longer holds the subscription path or the UUID;
    • the result keeps the host that was tested.
  • Card (ConfigHealthCard.vue, new shared/composables/useConfigHealth.ts):
    • an explanation per kind, saying where to look (e.g. "the TLS certificate of is not valid … check this domain in Domains");
    • the technical message on demand, wrapped inside the card;
    • a reason in words for each failed config ("The server closed the connection", "The TLS handshake failed", …).
  • Bell (usePanelNotifications.ts):
    • Config health problems also show as notifications, errors first: which app, what's wrong, and where the details are;
    • only for super admins, refreshed every 10 minutes.
  • Strings in en and fa (the only languages that have the Config health strings).

Screenshots

Before After
before after
before after
before after
before after

With the technical details and a failing app opened:

details

Tested

  • On main (panel restart):
    • the exact error reproduces when fetching with a name the certificate doesn't cover;
    • verify=False fetches it;
    • _host() picks the domain name;
    • a full real check completed with no fetch error.
  • Error kinds and cleanup: checked on sample messages (certificate, timeout, HTTP 404, refused, no config).
  • UI: checked with a sample certificate error put in redis, then the real result was restored: desktop, mobile, Persian RTL, and the bell (the error first, the failed-config count from total - ok, not from the 60-item list).
  • Deploy: the panel is deployed to main, node1 and node2.

Review

  • Confidence: High (>90%) — root cause reproduced and fixed, and the result format only gains fields (error_kind, host). Older results still render.
  • Complexity: Simple — the Config health module, its card and the bell.

🤖 Generated with Claude Code

Hiddify-Official and others added 2 commits October 23, 2026 03:57
The panel's notices (default domain, SSH password login, …) were banners
above every page.

- A bell in the topbar, next to the account icon, lists them; it is
  shown only while there are notices.
- A blinking red dot while some have not been seen; opening the list
  marks them seen (kept per browser, like dismissals). A notice whose
  text changes counts as new again. New ones are tagged until it closes.
- Each notice can be dismissed from the list, as from the banner; with
  none left the bell goes away.
- The banner component is removed; toasts for toast notices still show.
- Strings in all 7 languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… in the bell

The check fetched the subscription from the first domain, which can be the
server's bare IP: its certificate names the server's hostname, so the fetch
failed with an SSL hostname mismatch although nothing was wrong. A domain
name is now preferred; with only an IP the server asks itself without the
certificate check.

Errors get a kind (certificate, timeout, dns, unreachable, http, empty,
core) and the dashboard card explains each one and where to look, with the
technical message (subscription path removed) on demand and wrapped inside
the card. Failed configs get a reason in words. Config health problems also
show in the topbar notifications, errors first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🥷 Ninja i18n – 🛎️ Translations need to be updated

Project /project.inlang

lint rule new reports level link
Missing translation 125 warning contribute (via Fink 🐦)
Identical pattern 1 warning contribute (via Fink 🐦)

@hiddify-com
hiddify-com merged commit 154210e into hiddify:dev Oct 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants