semaphoreui/semaphore · warning

unexpected server challenge

Error message

unexpected server challenge: %s

What it means

During LOGIN-style auth, Next expects the server challenge to be exactly 'Username:' or 'Password:'. Any other prompt (localized text, extra whitespace, different wording) falls through to this error, which includes the offending challenge bytes.

Solutions

  1. Switch to a mechanism with fixed semantics (PLAIN over TLS) instead of relying on LOGIN prompt text.
  2. Extend the LOGIN handling to match the actual prompts your server sends (case-insensitive/prefix match).
  3. Check the error message for the exact challenge string and align either the server locale or the client matching.

Example fix

// before
case bytes.Equal(fromServer, []byte("Username:")):
    return []byte(a.username), nil
// after
switch {
case bytes.Contains(bytes.ToLower(fromServer), []byte("user")):
    return []byte(a.username), nil
case bytes.Contains(bytes.ToLower(fromServer), []byte("pass")):
    return []byte(a.password), nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

// probe the server's LOGIN prompts before auth, or pin the mechanism
if serverUsesLocalizedLoginPrompts {
    return errors.New("server LOGIN prompts are non-standard; use PLAIN over TLS instead")
}

Try / catch

resp, err := auth.Next(fromServer, true)
if err != nil && strings.HasPrefix(err.Error(), "unexpected server challenge:") {
    // log err for the exact prompt text; switch to PLAIN over TLS or patch prompt matching
    return fmt.Errorf("unsupported LOGIN prompt from server: %w", err)
}

Prevention

When it happens

Trigger: SMTP server performs LOGIN auth but prompts with non-standard strings (e.g. 'Username:', lowercase, localized messages, or base64-wrapped prompts), so bytes.Equal matches neither expected literal.

Common situations: Non-English SMTP servers (localized LOGIN prompts); Exchange/other servers using 'Username' without colon; custom relays with slightly different challenge text.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/01d18457441a8971. Report an issue: GitHub.

Appendix: source

Thrown at util/mailer/auth.go:64

}

func (a *plainOrLoginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
	if !more {
		return nil, nil
	}

	if a.authMethod == "PLAIN" {
		// We've already sent everything.
		return nil, errors.New("unexpected server challenge")
	}

	switch {
	case bytes.Equal(fromServer, []byte("Username:")):
		return []byte(a.username), nil
	case bytes.Equal(fromServer, []byte("Password:")):
		return []byte(a.password), nil
	default:
		return nil, fmt.Errorf("unexpected server challenge: %s", fromServer)
	}
}

View on GitHub (pinned to 1774ccb71a)