Skip to content

Connect to loopback when the server host is a wildcard address - #594

Merged
Blaizzy merged 2 commits into
Blaizzy:mainfrom
Lazarus-931:fix/server-host-loopback
Sep 21, 2026
Merged

Blaizzy merged 2 commits into
Blaizzy:mainfrom
Lazarus-931:fix/server-host-loopback

Conversation

@Lazarus-931

@Lazarus-931 Lazarus-931 commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Closes #568
Closes #593

Issue

Setting the server host to a wildcard address (0.0.0.0, used to expose the server to the LAN) breaks the in-app chat: the model picker stays on "Loading model · 100%" and messages can't be submitted, even though the same server serves external clients fine over the network. Switching the host back to 127.0.0.1 restores the UI. Reported independently in #568 and #593.

Cause

The host string was doing two jobs: the server's bind address (--host, where 0.0.0.0 correctly means "all interfaces") and the base URL the app uses to reach its own server. 0.0.0.0 is a valid bind address but not a routable destination, so the app's own requests to http://0.0.0.0:<port> — model readiness, metrics, and chat completions — never connect. That is why the load spinner never clears while the backend is healthy.

Fix

serverBaseURL (what the app connects to) maps a wildcard bind address to loopback: 0.0.0.0 → 127.0.0.1, :: → [::1]. The --host launch argument still receives the raw host, so the server keeps binding all interfaces and stays reachable on the LAN. Bind-conflict messages now report the configured host:port.

LAN endpoint discovery (advertising the machine's LAN address in the Developer panel) is deferred to a separate change, per review.

Impact on current users

The remap only touches the wildcard addresses:

  • Default 127.0.0.1: unchanged.
  • An explicit host / LAN IP: unchanged — the app connects to exactly that address.
  • 0.0.0.0 / ::: previously broken in-app; now the app connects over loopback while --host still binds all interfaces, so LAN exposure is preserved. Nothing relied on the app connecting to 0.0.0.0, because that never worked.

Verification

Local debug build with host set to 0.0.0.0: the model picker transitions from "Loading model · 100%" to ready and chat submits/streams; the server binds all interfaces (*:8080) and /health + /v1/models respond over 127.0.0.1. Regression checks with 127.0.0.1 (default) and an explicit LAN IP are unchanged; :: maps to [::1]. Regression tests cover the wildcard→loopback mapping for both IPv4 and IPv6.

Setting the server host to 0.0.0.0 (or ::) made the app build its own
client URL from that address and connect to http://0.0.0.0:<port>. A
wildcard is a valid bind address but not a routable destination, so the
app's own requests — model readiness, metrics, and chat completions —
never connected. The UI stayed on "Loading model · 100%" and messages
could not be sent, even though the server was healthy and reachable from
other machines.

Separate the two roles the host string was serving:

- serverBaseURL (what the app connects to) maps a wildcard bind address
  to loopback (0.0.0.0 -> 127.0.0.1, :: -> [::1]). The --host launch
  argument still receives the raw host, so the server keeps binding all
  interfaces and stays reachable on the LAN.
- advertisedBaseURL (used only for the Developer panel's endpoint display
  and copy) resolves the machine's LAN IP when the host is a wildcard, so
  the shown/copied endpoint is usable from other machines instead of the
  unroutable 0.0.0.0.

Fixes Blaizzy#568
Fixes Blaizzy#593
@Lazarus-931
Lazarus-931 marked this pull request as ready for review September 21, 2026 10:58

@Blaizzy Blaizzy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Alazar!

Lets merge the wildcard-to-loopback correction with regression tests, and handle LAN endpoint discovery separately.

The added LAN-address discovery needs more work:

  • IPv6 advertises an unreachable IPv4 endpoint. For host ::, advertisedBaseURL selects an IPv4 address. The bundled Uvicorn server creates an IPv6-only listener.
  • The interface selection is a heuristic. Preferring en0, then the first active interface, doesn’t reliably identify the intended LAN on machines with Ethernet, Wi-Fi, VPNs, or virtual interfaces. It also repeats interface enumeration whenever the computed property is read.
  • Bind errors should identify the configured bind address. Using the advertised LAN address can misleadingly report that address as occupied when the actual conflict concerns another interface covered by the wildcard.

@Lazarus-931

Copy link
Copy Markdown
Contributor Author

Thanks Alazar!

Lets merge the wildcard-to-loopback correction with regression tests, and handle LAN endpoint discovery separately.

The added LAN-address discovery needs more work:

* IPv6 advertises an unreachable IPv4 endpoint. For host ::, advertisedBaseURL selects an IPv4 address. The bundled Uvicorn server creates an IPv6-only listener.

* The interface selection is a heuristic. Preferring en0, then the first active interface, doesn’t reliably identify the intended LAN on machines with Ethernet, Wi-Fi, VPNs, or virtual interfaces. It also repeats interface enumeration whenever the computed property is read.

* Bind errors should identify the configured bind address. Using the advertised LAN address can misleadingly report that address as occupied when the actual conflict concerns another interface covered by the wildcard.

will do, maybe a stacked for for the latter ontop with these fixes addressed!

@Blaizzy

Blaizzy commented Sep 21, 2026

Copy link
Copy Markdown
Owner

No need to stack, just remove those keep the PR focused so we can merge it, then you can later add it.

Per PR review, split out the LAN-address discovery (advertisedBaseURL and
interface enumeration) so this change is only the wildcard-to-loopback
connect correction and its regression tests. The server-endpoint display
uses the connect URL again, and bind-conflict messages now report the
configured host:port instead of a resolved address.

@Blaizzy Blaizzy left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@Blaizzy
Blaizzy merged commit 57286db into Blaizzy:main Sep 21, 2026
3 checks 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

2 participants