projectdiscovery/katana · error
invalid group ID
Error message
invalid group ID
What it means
Thrown when strconv.Atoi fails to parse ChromeUser.Gid. Same as the UID case but for the group ID: katana cannot chown the temp chrome data directory, so it deletes the directory and aborts page creation.
Source
Thrown at pkg/engine/headless/browser/browser.go:397
// 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
}
}
browser, err := l.launchBrowserWithDataDir(tempDir)
if err != nil {View on GitHub (pinned to e3e742739c)
Solutions
- Use user.Lookup("chrome") / user.LookupGroup to obtain properly populated Uid and Gid strings.
- Validate both fields up front with strconv.Atoi and fall back to ChromeUser=nil when invalid.
- Correct the account's primary group in /etc/passwd (or the NSS/LDAP source) if Gid is missing.
- If ownership change is not required, leave ChromeUser nil to use the default temp directory.
Example fix
// before
opts.ChromeUser = &user.User{Username: "chrome", Uid: "1000"} // Gid missing
// after
u, err := user.Lookup("chrome")
if err != nil {
return err
}
if _, err := strconv.Atoi(u.Gid); err != nil {
return fmt.Errorf("gid for user chrome is not numeric: %q", u.Gid)
}
opts.ChromeUser = u Defensive patterns
Strategy: validation
Validate before calling
if opts.ChromeUser != nil {
if _, err := strconv.Atoi(opts.ChromeUser.Gid); err != nil {
return fmt.Errorf("ChromeUser.Gid %q is not numeric", opts.ChromeUser.Gid)
}
} Type guard
func hasNumericGid(u *user.User) bool {
_, err := strconv.Atoi(u.Gid)
return err == nil
} Try / catch
page, err := l.createBrowserPageFunc(...)
if err != nil && strings.Contains(err.Error(), "invalid group ID") {
l.opts.ChromeUser = nil // retry without dedicated chrome user
page, err = l.createBrowserPageFunc(...)
} Prevention
- Use user.Lookup/user.LookupGroup to fill Gid correctly.
- Check the account's primary group exists in /etc/passwd or the NSS backend.
- Validate Gid numerically before assigning ChromeUser.
- Skip ChromeUser entirely when no group-based isolation is required.
When it happens
Trigger: ChromeUser.Gid is not a valid decimal integer string — empty or non-numeric — when the user.User struct was constructed manually or came from a directory service that did not populate Gid.
Common situations: Hand-built user.User missing Gid; NSS/LDAP lookups returning incomplete entries; pasting a uid into the Gid field with a typo; Windows hosts where user.Lookup semantics differ.
Related errors
- invalid user ID
- unsupported strategy
- could not create temporary chrome data directory
- could not change ownership of chrome data directory
- could not create new page
AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03).
Data as JSON: /api/errors/c2f4f5ecae509056.
Report an issue: GitHub.