fix: handle list-type host in settings and fix [object Object] error display#908
fix: handle list-type host in settings and fix [object Object] error display#908fqx wants to merge 2 commits into
Conversation
…display When users manually set `host` to a YAML list in settings.yaml, the backend would store the list object in ServerSettings.host (typed str), causing the web UI to receive a non-string value. Alpine.js x-model then displayed "[object Object]" in the host input, and saving triggered a Pydantic 422 whose array-of-objects detail was joined to "[object Object]". - settings.py: normalize host to string in from_dict() — list values are joined with ", " so the web UI can display and edit them normally - dashboard.js: extract .msg from Pydantic error detail objects instead of calling .join() directly on them, preventing "[object Object]" in all error toasts (fixes two call sites) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Users can now enter multiple bind addresses in the host field separated by commas (e.g. "127.0.0.1, 0.0.0.0"). The existing YAML list format is also handled via the from_dict() normalization added in the previous commit. Changes: - cli.py: split host string by comma before calling uvicorn.run(); print one URL line per address; asyncio.create_server() binds a socket for each host in the list natively - utils/network.py: add is_valid_bind_host() which accepts all valid IPs (including 0.0.0.0 and ::) and hostnames — unlike is_valid_alias() which rejects unspecified addresses - admin/routes.py: validate each comma-separated part of the host field on save so invalid values are rejected with a 400 before they can cause a crash on server restart Backward-compatible: single-address strings and legacy YAML list values both continue to work without any settings migration. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SummaryThis PR enables users to specify multiple bind addresses directly from the web UI, rather than being limited to a single address or the catch-all Why it matters: Binding only to specific interfaces is more secure than listening on all interfaces. A common use case is exposing the server locally and over a private overlay network such as Tailscale, without opening it to every interface on the machine — for example: While this was already supported via manual edits to What changed:
Existing single-address configs and legacy YAML list values continue to work without any migration. |
Superseded by a new PR that adapts to the
uvicorn.Config + bind_socket()refactor introduced in #1526. The core logic is the same but thecli.pychanges are rewritten to work with the new pre-bind approach.