macOS: Agent DNS can fail after a user-session transition until Avibe restarts
#891 opened on Jul 13, 2026
Repository metrics
- Stars
- (489 stars)
- PR merge metrics
- (Avg merge 4h 21m) (286 merged PRs in 30d)
Description
Summary
On macOS, Avibe has once remained running across a user-session transition while an existing agent process tree lost system hostname resolution. Inside the affected agent, gh, git, and curl could no longer resolve hostnames, even though raw network access still worked and other logged-in users were unaffected. Restarting Avibe from a healthy login session restored DNS.
The important boundary is now narrower than the original report: Fast User Switching by itself is not sufficient to reproduce the failure. The remaining hypothesis is that the original user's Aqua login session was actually logged out or otherwise torn down, while Avibe's unmanaged detached processes survived with stale bootstrap/audit-session state.
Original observed behavior
From the affected agent shell:
socket.getaddrinfo("localhost", 80)succeeded, while public DNS names failed.- Raw UDP/53 queries and direct-IP TLS requests succeeded.
curl --resolve ...succeeded, isolating the failure to system name resolution.scutil --dnsreturned no usable DNS configuration.- User-session services such as Keychain were also unavailable.
- Other users and ordinary terminals on the same Mac still had working DNS.
- Restarting the full Avibe process tree restored service immediately.
This breaks any long-running agent task that needs GitHub, package registries, or external APIs.
Updated findings (2026-07-18)
- Apple documents Fast User Switching as multiple users remaining logged in at the same time: https://support.apple.com/guide/mac-help/mchlp2439/mac
- The current Mac is in that exact state: another account owns the console while the Avibe account remains logged in.
- The live Avibe service has
PPID=1, butlaunchctl print pid/<pid>reports the same Aqua audit session ID aslaunchctl print gui/<uid>. - A live Codex child and its shell inherit that same audit session, and DNS works normally while the Avibe user is not the foreground console user.
- Avibe still launches the service with
Popen(..., start_new_session=True). That creates a POSIX session/process group and explains the eventualPPID=1; it does not prove that the process left the Aqua Mach bootstrap domain. - No PR or merged change has addressed this issue yet.
Therefore the original claim that PPID=1 directly means "outside the login session" is incorrect. Fast User Switching remains a useful trigger to test, but the failure needs evidence captured while it is active.
Working hypothesis
The likely sequence is:
- Avibe starts in user A's Aqua login domain.
- The machine switches to user B.
- User A is later truly logged out, automatically logged out, or has the Aqua login domain torn down.
- Avibe's detached, unmanaged process survives because launchd does not own it as a per-login LaunchAgent.
- The surviving service and agent processes retain invalid login/bootstrap connections. System resolver and other user-session clients can no longer reconnect.
vibe restartrun from a healthy login session creates a fresh process tree in the current Aqua domain and restores DNS.
This is still a hypothesis. An mDNSResponder restart may expose the stale state, but it is not yet proven to be the root cause.
Evidence to capture before the next restart
Capture this for both the Avibe service PID and the affected backend/agent PID:
stat -f '%Su' /dev/console
who
launchctl print pid/<service-pid>
launchctl print pid/<agent-pid>
launchctl print gui/$(id -u)
ps -o pid=,ppid=,pgid=,user=,command= -p <service-pid>,<agent-pid>
scutil --dns
python3 -c 'import socket; print(socket.getaddrinfo("api.github.com", 443))'
The decisive signal is whether the affected process ASID/bootstrap context no longer matches the current gui/<uid> login domain, or whether that GUI domain was destroyed and recreated while the old Avibe PID survived.
Also record whether the transition was:
- screen lock/unlock;
- VNC disconnect/reconnect;
- Fast User Switching with both users still logged in;
- explicit logout/login;
- automatic logout of an inactive user;
- sleep/wake or VPN/network reconfiguration.
Proposed direction
If the stale-login-domain hypothesis is confirmed, fix the macOS service lifecycle, not DNS itself:
- Run Avibe as a per-user LaunchAgent in the user's
gui/<uid>login domain, not as a system LaunchDaemon. - Keep
vibe start,vibe stop, andvibe restartas the public interface; internally map them to LaunchAgent bootstrap/bootout/kickstart semantics. - Let Fast User Switching keep Avibe alive while the original user remains logged in.
- On true logout, allow the old Avibe process to terminate with the Aqua session. Start a fresh instance on the next login instead of preserving an orphan with stale session services.
- Ensure upgrades restart through the LaunchAgent owner rather than spawning another detached supervisor.
- Preserve the backend environment explicitly because LaunchAgents do not inherit the user's interactive shell environment.
For a future bundled macOS app, use Apple's SMAppService.agent(plistName:) registration path rather than manual plist installation: https://developer.apple.com/documentation/servicemanagement/smappservice
Do not work around this with /etc/hosts, custom public DNS queries, or backend-specific retries. Those approaches break VPN/split-DNS behavior and do not repair other stale user-session services.
Acceptance criteria
- Lock/unlock, VNC disconnect, and Fast User Switching do not break DNS for existing or newly spawned agents.
- If the Avibe user truly logs out, no old Avibe service or agent process survives with the destroyed login session.
- Avibe starts in the new Aqua domain after the next login and its service/agent ASIDs match
gui/<uid>. vibe start,vibe stop,vibe restart, and upgrade remain reliable and idempotent.- Claude, Codex, and OpenCode inherit the same healthy login/bootstrap context.
- Linux and Windows lifecycle behavior is unchanged.