AdguardTeam/AdGuardHome · error

login: expected length %d, got %d

Error message

login: expected length %d, got %d

What it means

bboltDecode validates that the trailing name bytes match the 2-byte big-endian length prefix; a mismatch means the record is internally inconsistent and cannot be safely decoded. Like error 61, it points to corrupted or foreign data in the sessions bucket.

Source

Thrown at internal/aghuser/sessionstorage.go:294

	// bboltSessionNameLen is the length of the name field in the binary entry
	// stored in bbolt.
	bboltSessionNameLen = 2
)

// bboltDecode deserializes decodes a binary data into a session.
func bboltDecode(data []byte) (s *Session, err error) {
	if len(data) < bboltSessionExpireLen+bboltSessionNameLen {
		return nil, fmt.Errorf("length of the data is less than expected: got %d", len(data))
	}

	expireData := data[:bboltSessionExpireLen]
	nameLenData := data[bboltSessionExpireLen : bboltSessionExpireLen+bboltSessionNameLen]
	nameData := data[bboltSessionExpireLen+bboltSessionNameLen:]

	nameLen := binary.BigEndian.Uint16(nameLenData)
	if len(nameData) != int(nameLen) {
		return nil, fmt.Errorf("login: expected length %d, got %d", nameLen, len(nameData))
	}

	expire := binary.BigEndian.Uint32(expireData)

	return &Session{
		Expire:    time.Unix(int64(expire), 0),
		UserLogin: Login(nameData),
	}, nil
}

// bboltEncode serializes a session properties into a binary data.
func bboltEncode(s *Session) (data []byte) {
	data = make([]byte, bboltSessionExpireLen+bboltSessionNameLen+len(s.UserLogin))

	expireData := data[:bboltSessionExpireLen]
	nameLenData := data[bboltSessionExpireLen : bboltSessionExpireLen+bboltSessionNameLen]
	nameData := data[bboltSessionExpireLen+bboltSessionNameLen:]

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Delete the sessions db file so invalid records are purged and users re-login
  2. Pin one AdGuard Home version (avoid downgrade after upgrade)
  3. Run bbolt integrity checks / restore backup
Defensive patterns

Strategy: fallback

Type guard

func sessionNameLenMatches(b []byte) bool {
	if len(b) < 6 { return false }
	return int(binary.BigEndian.Uint16(b[4:6])) == len(b)-6
}

Try / catch

// treat as corrupt record: purge db, restart clean
if err != nil && strings.Contains(err.Error(), "login: expected length") { purgeSessionDB() }

Prevention

When it happens

Trigger: A bucket value where the declared login-name length does not equal the remaining bytes — truncated record, tampering, or an incompatible serialization version.

Common situations: Crash during a session write; manual editing of the db; format drift between versions.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/95622f624254ebbe. Report an issue: GitHub.