AdguardTeam/AdGuardHome · error

login: expected length

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.

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.

Appendix: 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)