kovidgoyal/kitty · warning

passwd line has %d colon delimited fields instead of 7

Error message

passwd line has %d colon delimited fields instead of 7

What it means

ParsePasswdLine splits a line of /etc/passwd (or DSCL output) on colons and expects exactly 7 fields: name, passwd, uid, gid, gecos, home, shell. Any other field count produces this error. It is a strict format validation of passwd-style records.

Source

Thrown at tools/utils/passwd.go:29

	"strconv"
	"strings"
	"sync"

	"howett.net/plist"
)

var _ = fmt.Print

type PasswdEntry struct {
	Username, Pass, Uid, Gid, Gecos, Home, Shell string
}

func ParsePasswdLine(line string) (PasswdEntry, error) {
	parts := strings.Split(line, ":")
	if len(parts) == 7 {
		return PasswdEntry{parts[0], parts[1], parts[2], parts[3], parts[4], parts[5], parts[6]}, nil
	}
	return PasswdEntry{}, fmt.Errorf("passwd line has %d colon delimited fields instead of 7", len(parts))
}

func ParsePasswdDatabase(raw string) (ans map[string]PasswdEntry) {
	scanner := NewLineScanner(raw)
	ans = make(map[string]PasswdEntry)
	for scanner.Scan() {
		line := scanner.Text()
		if entry, e := ParsePasswdLine(line); e == nil {
			ans[entry.Uid] = entry
		}
	}
	return ans
}

func ParsePasswdFile(path string) (ans map[string]PasswdEntry, err error) {
	raw, err := os.ReadFile(path)
	if err != nil {
		return nil, err

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Inspect the reported line and its field count; fix or discard malformed entries upstream.
  2. If GECOS may contain colons, split with strings.SplitN(line, ":", 7) so extra colons stay in the GECOS field.
  3. Skip blank/comment lines before calling ParsePasswdLine.
  4. Validate input with a regexp like ^([^:]*:){6}[^:]*$ before parsing.

Example fix

// before
parts := strings.Split(line, ":")
// after
parts := strings.SplitN(line, ":", 7)
if len(parts) == 7 { ... }
Defensive patterns

Strategy: validation

Validate before calling

if !passwdLineRE.MatchString(line) {
    return nil, fmt.Errorf("skipping malformed passwd line: %q", line)
}
// var passwdLineRE = regexp.MustCompile(`^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*$`)

Try / catch

entry, err := utils.ParsePasswdLine(line)
if err != nil {
    log.Printf("skipping bad passwd line %q: %v", line, err)
    continue
}

Prevention

When it happens

Trigger: Feeding ParsePasswdLine a malformed line: missing trailing fields, extra colons in GECOS (e.g. a comment containing ':'), empty lines with colons, or Windows-style line endings leaving stray characters.

Common situations: Parsing hand-edited /etc/passwd files, passwd files from exotic NSS backends, or test fixtures that abbreviate lines. Also GECOS fields containing colons, which inflate the field count.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/608a66116d52b1d7. Report an issue: GitHub.