A custom latency test URL that http.NewRequest rejects made a spawned
goroutine dereference nil and exit the process; the URL is validated
before any goroutine starts and the request error is handled. A
Shadowsocks link whose plugin field has no ";" panicked the parser, and
from the automatic subscription update that goroutine was unrecovered;
the parser accepts it and each updater recovers and logs.
The DNS module took the last non-bootstrap upstream as the fallback
while the template emitted upstreams in rule order with deduplication,
so a catch-all rule anywhere but last, or one whose upstream was
deduplicated, was not the fallback. The template names the fallback in
a new default_upstream field and the module honours it.
PUT /routingA stored the rules without regenerating the running core.
It goes through ApplyCoreConfig like the other config writers, with
restore on failure. UpdateSubscription logged a failed core reload and
answered success; it returns the error. PATCH /subscription joins the
mutation turn.
Subscription fetching retried through a direct connection when the
selected proxy failed, leaking the subscription URL; it returns the
error. Subscription documents are capped at 32 MiB and downloaded
assets at 256 MiB. PUT /gfwList validates the downloaded file as a
geosite list before replacing the working one.
The login handler took its one-at-a-time semaphore before reading the
body, so a client sending headers and no body blocked every login; the
body is read first and the HTTP server has header and idle timeouts.
Share links: a VLESS or VMess link without a numeric port is rejected
at parse time instead of producing port 0; an SSR link with a password
that is not base64 is rejected instead of importing empty; the SIP003
path gets its leading slash prepended, not a trailing one appended.
The macOS system proxy quoted shell arguments with strconv.Quote,
which leaves $(...) live; values are single-quoted. The Windows system
proxy snapshot includes AutoConfigURL, which teardown deleted and never
restored. Latency test responses with a non-2xx status are closed. The
version response carries the docker flag the GUI's port hints read.
PUT /dnsRules regenerates the running core's config and restores the
previous rules when that fails; SetPorts restores the previous ports
when the restart fails. The HTTP latency test drops subscription
entries as intended. The remote GFWList version request has a deadline
and its cache a one-hour TTL. CheckUpdate picks the index of the running
architecture and closes the body on every path.
Errors that reach the GUI were written for the log: "ResolveURL failed:
invalid parameters", "httpGetUsingSpecificClient: response is nil",
"LocateServerRaw: invalid TYPE", "bad request", "illegal base64 data at
input byte 18". Reword the messages that can reach a user so each names
the input that was rejected (link scheme, missing password, port, server
id, request field), states the expected form for malformed input, drops
Go function names, keeps the %w chain so errors.Is/As still work, and
never echoes passwords, tokens or full share links (hosts only).
Messages the GUI string-matches ("invalid config", "the last request is
being processed") are unchanged.