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

  1. Run the query as root or in the same launchd domain (gui/UID) as the target so findServiceByPID can see the service.
  2. Check `sudo launchctl list` and `launchctl print system/<label>` manually to locate the owning domain.
  3. Treat the process as not launchd-managed and skip plist enrichment.
  4. 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

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


AI-assisted analysis of pranshuparmar/witr@dc4fa1da82 (2026-09-01). Data as JSON: /api/errors/b201ff34b1243981. Report an issue: GitHub.