crowdsecurity/crowdsec · error

while getting process attributes: %w

Error message

while getting process attributes: %w

What it means

CreateCmd wraps any failure from getProcessAttr, which resolves the configured plugin user/group to uid/gid values via os/user lookups. The wrapper preserves the underlying cause (%w) while attributing it to the plugin process-attribute setup step. It only fires when both user and group are configured for the notification plugin.

Source

Thrown at pkg/csplugin/utils.go:31

	"os/user"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"

	"golang.org/x/sys/unix"
)

func (pb *PluginBroker) CreateCmd(ctx context.Context, binaryPath string) (*exec.Cmd, error) {
	var err error
	cmd := exec.CommandContext(ctx, binaryPath)
	if pb.pluginProcConfig.User != "" || pb.pluginProcConfig.Group != "" {
		if pb.pluginProcConfig.User == "" || pb.pluginProcConfig.Group == "" {
			return nil, errors.New("while getting process attributes: both plugin user and group must be set")
		}
		cmd.SysProcAttr, err = getProcessAttr(pb.pluginProcConfig.User, pb.pluginProcConfig.Group)
		if err != nil {
			return nil, fmt.Errorf("while getting process attributes: %w", err)
		}
		cmd.SysProcAttr.Credential.NoSetGroups = true
	}
	return cmd, err
}

func getUID(username string) (uint32, error) {
	u, err := user.Lookup(username)
	if err != nil {
		return 0, err
	}
	uid, err := strconv.ParseInt(u.Uid, 10, 32)
	if err != nil {
		return 0, err
	}
	if uid < 0 || uid > math.MaxInt32 {
		return 0, errors.New("out of bound uid")
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Check which user/group is configured for the plugin and verify it exists on the host: getent passwd <user> and getent group <group>
  2. Create the missing user/group, or remove/adjust the user and group keys in the plugin's config so they match an existing account
  3. Read the wrapped %w cause in the full error chain to see whether it was the user or the group lookup that failed

Example fix

# before (config/auth.yaml)
name: crowdsecurity/http
user: crowdsec
group: crowdsec
# after
name: crowdsecurity/http
user: www-data
group: www-data
Defensive patterns

Strategy: validation

Validate before calling

if cfg.User != "" || cfg.Group != "" {
    if _, err := user.Lookup(cfg.User); err != nil {
        return fmt.Errorf("plugin user %q does not exist", cfg.User)
    }
    if _, err := user.LookupGroup(cfg.Group); err != nil {
        return fmt.Errorf("plugin group %q does not exist", cfg.Group)
    }
}

Try / catch

cmd, err := CreateCmd(...)
if err != nil {
    var ue *user.UnknownUserError
    if errors.As(err, &ue) { log.Fatalf("create plugin user first: %v", ue) }
    return err
}

Prevention

When it happens

Trigger: loadNotificationPlugin calls CreateCmd with pluginProcConfig.User and pluginProcConfig.Group both set, and getProcessAttr fails because the username or groupname cannot be resolved to a uid/gid on the system (or the underlying unix call otherwise errors).

Common situations: config/auth.yaml (or profiles notification_config) specifies a 'user'/'group' for a plugin that does not exist on the host, e.g. copied config from another machine referencing 'crowdsec' user before it was created; running in a container where the user/group entries are absent from /etc/passwd or /etc/group.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/d8e60cdc7f9493bc. Report an issue: GitHub.