pranshuparmar/witr · warning
process not managed by a named launchd service: %s
Error message
process not managed by a named launchd service: %s
What it means
launchctl blame returned a 'blame reason' string (e.g. 'speculative', 'non-ipc demand', 'ipc (mach)') rather than a service path, meaning the process is associated with launchd activity but not attributable to a named service. GetServiceLabel then tries findServiceByPID; when that also finds no label it returns this error including the blame reason.
Source
Thrown at internal/launchd/plist.go:83
}
// Output format varies:
// - "system/com.apple.example" or "gui/501/com.example.app" (real service)
// - "speculative", "non-ipc demand", "launch job demand", "ipc (mach)" (blame reasons)
line := strings.TrimSpace(string(out))
if line == "" {
return "", "", fmt.Errorf("no service label found for pid %d", pid)
}
// Check if this is a real service path (contains "/" and starts with domain)
if !strings.Contains(line, "/") {
// This is a blame reason, not a service label
// Try to find the service by querying launchctl list
label, domain := findServiceByPID(pid)
if label != "" {
return label, domain, nil
}
return "", "", fmt.Errorf("process not managed by a named launchd service: %s", line)
}
// Parse domain and label from service path
parts := strings.SplitN(line, "/", 2)
if len(parts) < 2 {
return line, "", nil
}
domain := parts[0]
label := parts[1]
// Handle gui/501/label format
if domain == "gui" {
subParts := strings.SplitN(label, "/", 2)
if len(subParts) == 2 {
domain = "gui/" + subParts[0]
label = subParts[1]
}View on GitHub (pinned to dc4fa1da82)
Solutions
- Run the query as root or in the same launchd domain (gui/UID) as the target so findServiceByPID can see the service.
- Check `sudo launchctl list` and `launchctl print system/<label>` manually to locate the owning domain.
- Treat the process as not launchd-managed and skip plist enrichment.
- Search the plist directories (/System/Library/LaunchDaemons, ~/Library/LaunchAgents) for the executable path instead of relying on blame.
Example fix
// before
label, _, err := launchd.GetServiceLabel(pid) // 'process not managed ...: speculative'
// after
label, _, err := launchd.GetServiceLabel(pid)
if err != nil && strings.Contains(err.Error(), "not managed by a named launchd service") {
// helper/xpc process: fall back to executable path lookup
return lookupByExecutablePath(pid)
} Defensive patterns
Strategy: fallback
Try / catch
label, domain, err := launchd.GetServiceLabel(pid)
if err != nil {
var nlm *notManagedError
if errors.As(err, &nlm) || strings.Contains(err.Error(), "not managed by a named launchd service") {
return lookupByExecutablePath(pid) // XPC/helper fallback
}
return err
} Prevention
- Expect blame reasons for XPC helpers and transient agents; have a path-based fallback ready.
- Query as root or in the target's launchd domain so findServiceByPID can succeed.
- Search plist directories by executable path when blame returns a reason string.
When it happens
Trigger: Calling GetServiceLabel on a process whose blame output contains a slash-less reason string and for which findServiceByPID finds no entry in `launchctl list`: daemons started via legacy mechanisms, xpc/helper processes, or processes whose service is outside the caller's launchd domain.
Common situations: Inspecting XPC helper processes of an app; system daemons not visible in the user's gui domain; Spotlight/background agents spawned transiently; running unprivileged so `launchctl list` can't see the owning domain.
Related errors
- launchctl blame failed: %w
- no service label found for pid %d
- listfds returned partial record
- failed to convert plist: %w
- no process ancestry found
AI-assisted analysis of pranshuparmar/witr@dc4fa1da82 (2026-09-01).
Data as JSON: /api/errors/b201ff34b1243981.
Report an issue: GitHub.