projectdiscovery/katana · error

invalid user ID

Error message

invalid user ID

What it means

Thrown when strconv.Atoi fails to parse ChromeUser.Uid. Katana needs the UID as an integer to os.Chown the freshly created temp chrome data directory. The temp dir is removed before returning to avoid leaking stale profile data.

Source

Thrown at pkg/engine/headless/browser/browser.go:392

	var tempDir string
	shouldCleanupTempDir := false

	if l.opts.ChromeWSUrl == "" {
		if l.opts.UserDataDir != "" {
			// Use user-provided data directory (preserve sessions/cookies)
			tempDir = l.opts.UserDataDir
			shouldCleanupTempDir = false
		} else if l.opts.ChromeUser != nil {
			var err error
			tempDir, err = os.MkdirTemp(l.opts.ChromeUser.HomeDir, "chrome-data-*")
			if err != nil {
				return nil, errors.Wrap(err, "could not create temporary chrome data directory")
			}

			uid, err := strconv.Atoi(l.opts.ChromeUser.Uid)
			if err != nil {
				_ = os.RemoveAll(tempDir)
				return nil, errors.Wrap(err, "invalid user ID")
			}
			gid, err := strconv.Atoi(l.opts.ChromeUser.Gid)
			if err != nil {
				_ = os.RemoveAll(tempDir)
				return nil, errors.Wrap(err, "invalid group ID")
			}
			if err := os.Chown(tempDir, uid, gid); err != nil {
				_ = os.RemoveAll(tempDir)
				return nil, errors.Wrap(err, "could not change ownership of chrome data directory")
			}
			shouldCleanupTempDir = true
		} else {
			var err error
			tempDir, err = os.MkdirTemp("", "katana-chrome-data-*")
			if err != nil {
				return nil, errors.Wrap(err, "could not create temporary chrome data directory")
			}
			shouldCleanupTempDir = true

View on GitHub (pinned to e3e742739c)

Solutions

  1. Populate ChromeUser via user.Lookup("chrome"), which fills Uid as a decimal string, instead of building the struct by hand.
  2. Validate before use: if _, err := strconv.Atoi(u.Uid); err != nil fall back to ChromeUser=nil.
  3. Check /etc/passwd (or the NSS backend) that the account has a numeric UID; fix the directory service entry if empty.
  4. If no ownership change is needed, leave ChromeUser nil so katana uses the default temp dir path.

Example fix

// before
opts.ChromeUser = &user.User{Username: "chrome", HomeDir: "/home/chrome"} // Uid empty
// after
u, err := user.Lookup("chrome")
if err != nil {
    return err
}
opts.ChromeUser = u
Defensive patterns

Strategy: validation

Validate before calling

if opts.ChromeUser != nil {
    if _, err := strconv.Atoi(opts.ChromeUser.Uid); err != nil {
        return fmt.Errorf("ChromeUser.Uid %q is not numeric", opts.ChromeUser.Uid)
    }
}

Type guard

func hasNumericID(u *user.User) bool {
    _, uidErr := strconv.Atoi(u.Uid)
    _, gidErr := strconv.Atoi(u.Gid)
    return uidErr == nil && gidErr == nil
}

Try / catch

page, err := l.createBrowserPageFunc(...)
if err != nil && strings.Contains(err.Error(), "invalid user ID") {
    l.opts.ChromeUser = nil // retry without dedicated chrome user
    page, err = l.createBrowserPageFunc(...)
}

Prevention

When it happens

Trigger: ChromeUser.Uid is not a valid decimal integer string — empty ("") or non-numeric — typically when the *user.User struct was constructed manually or came from a directory service that did not populate Uid.

Common situations: Hand-built user.User{Username: "chrome"} without Uid; LDAP/SSSD/NSS lookups returning incomplete entries; populating Uid with a username instead of a number; unusual passwd formats.

Related errors


AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03). Data as JSON: /api/errors/0cf14f22fcc88b98. Report an issue: GitHub.