gravitational/teleport · error
could not connect to the VNet daemon within the timeout
Error message
could not connect to the VNet daemon within the timeout
What it means
Raised in startByCalling (lib/vnet/daemon/client_darwin.go:239) as the context.Cause of a 20-second deadline. The C.StartVnet XPC call can hang if the daemon cannot be successfully spawned, so the client bounds the start attempt; if no response arrives within 20 seconds this error is returned (wrapped with 'connecting to the VNet daemon').
Source
Thrown at lib/vnet/daemon/client_darwin.go:239
return "not registered"
case ServiceStatusEnabled:
return "enabled"
case ServiceStatusRequiresApproval:
return "requires approval"
case ServiceStatusNotFound:
return "not found"
case ServiceStatusNotSupported:
return "not supported"
default:
return strconv.Itoa(int(s))
}
}
func startByCalling(ctx context.Context, bundlePath string, config Config) error {
// C.StartVnet might hang if the daemon cannot be successfully spawned.
const daemonStartTimeout = 20 * time.Second
ctx, cancel := context.WithTimeoutCause(ctx, daemonStartTimeout,
errors.New("could not connect to the VNet daemon within the timeout"))
defer cancel()
defer C.InvalidateDaemonClient()
errC := make(chan error, 1)
go func() {
req := C.StartVnetRequest{
bundle_path: C.CString(bundlePath),
service_credential_path: C.CString(config.ServiceCredentialPath),
client_application_service_addr: C.CString(config.ClientApplicationServiceAddr),
}
defer func() {
C.free(unsafe.Pointer(req.bundle_path))
C.free(unsafe.Pointer(req.service_credential_path))
C.free(unsafe.Pointer(req.client_application_service_addr))
}()
View on GitHub (pinned to 1283425b60)
Solutions
- Check launchd and daemon logs (Console.app, `log show --predicate 'process == "tsh"'`) to see why the daemon did not spawn or respond.
- Verify the app bundle path and daemon label are correct; re-register the daemon (RegisterDaemon) and retry.
- Reboot the Mac or bootout/bootstrap the launchd job to clear a stuck service, then retry tsh vnet start.
Defensive patterns
Strategy: retry
Validate before calling
// verify the daemon binary exists and launchd job is defined before attempting start
if _, err := os.Stat(bundlePath); err != nil {
return fmt.Errorf("daemon bundle missing at %s: %w", bundlePath, err)
} Try / catch
err := client.RegisterAndCall(ctx, bundlePath, cfg)
if err != nil && strings.Contains(err.Error(), "could not connect to the VNet daemon within the timeout") {
// inspect launchd/daemon logs, re-register, then retry once
err = client.RegisterAndCall(ctx, bundlePath, cfg)
} Prevention
- Keep a bounded retry around daemon start, mirroring the 20s timeout.
- Monitor daemon startup logs for spawn failures or hangs.
- Re-register the daemon after bundle or label changes.
When it happens
Trigger: RegisterAndCall -> startByCalling where the daemon fails to spawn or never replies to the StartVnet XPC message: launchd job misconfigured, daemon binary failing to launch, XPC service stuck, or the daemon deadlocked on startup.
Common situations: Corrupted or invalid app bundle; daemon crashing silently at spawn; launchd backpressure on a busy system; conflicting/stale daemon job definition; daemon blocked during startup handshake.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- VNet is already running
- XPC connection interrupted
- code signing requirement failed
- XPC connection invalid
- the background item was not enabled within the timeout
AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02).
Data as JSON: /api/errors/0e917082915aa529.
Report an issue: GitHub.