Problem
When switching from a network where the corporate proxy is unreachable (e.g. mobile hotspot) back to the corporate network, alpaca gets stuck in DIRECT mode for up to 5 minutes despite the proxy being reachable again.
Root Cause
The sequence of events:
- On hotspot: proxy unreachable →
blockProxy() adds it to blocklist (5 min TTL) → requests fall through to DIRECT (from ; DIRECT in PAC)
- Switch back to corporate network → new IP assigned
- Next request triggers
checkForUpdates() → addrsChanged() returns true → download() returns PAC bytes → blocklist is reset via pf.blocked = newBlocklist() ✓
- But: a concurrent request (from system apps like Defender, Edge etc.) hits
handleConnect() / proxyRequest() at the same moment. The TCP handshake to the proxy fails because the network is not fully stable yet → blockProxy() immediately re-adds the proxy to the blocklist
- From this point:
addrsChanged() returns false (addresses have not changed since step 3) → blocklist is never cleared again → proxy stays blocked for the full 5 minutes
Environment
- macOS (Apple Silicon)
- Alpaca v2.0.13
- Local PAC file (
file://) with "PROXY corporate-proxy:8080; DIRECT"
- LaunchAgent with
KeepAlive=true
- System proxy pointing at alpaca (so GUI apps like Edge also route through it)
Suggested Fix
Add a grace period after addrsChanged() returns true, during which blockProxy() is suppressed. This would give the network time to stabilize before alpaca starts evaluating proxy reachability. Similar to Chrome's kDelayAfterNetworkChangesMs concept.
Alternatively, reduce the blocklist TTL when a recent network change was detected (e.g. 5 seconds instead of 5 minutes).
Workaround
Restart alpaca after network switch:
pkill -9 alpaca # launchd restarts it via KeepAlive
Problem
When switching from a network where the corporate proxy is unreachable (e.g. mobile hotspot) back to the corporate network, alpaca gets stuck in DIRECT mode for up to 5 minutes despite the proxy being reachable again.
Root Cause
The sequence of events:
blockProxy()adds it to blocklist (5 min TTL) → requests fall through toDIRECT(from; DIRECTin PAC)checkForUpdates()→addrsChanged()returns true →download()returns PAC bytes → blocklist is reset viapf.blocked = newBlocklist()✓handleConnect()/proxyRequest()at the same moment. The TCP handshake to the proxy fails because the network is not fully stable yet →blockProxy()immediately re-adds the proxy to the blocklistaddrsChanged()returns false (addresses have not changed since step 3) → blocklist is never cleared again → proxy stays blocked for the full 5 minutesEnvironment
file://) with"PROXY corporate-proxy:8080; DIRECT"KeepAlive=trueSuggested Fix
Add a grace period after
addrsChanged()returns true, during whichblockProxy()is suppressed. This would give the network time to stabilize before alpaca starts evaluating proxy reachability. Similar to Chrome'skDelayAfterNetworkChangesMsconcept.Alternatively, reduce the blocklist TTL when a recent network change was detected (e.g. 5 seconds instead of 5 minutes).
Workaround
Restart alpaca after network switch:
pkill -9 alpaca # launchd restarts it via KeepAlive