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
- Switch to a mechanism with fixed semantics (PLAIN over TLS) instead of relying on LOGIN prompt text.
- Extend the LOGIN handling to match the actual prompts your server sends (case-insensitive/prefix match).
- 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
- Prefer PLAIN over TLS instead of LOGIN to avoid dependence on prompt text.
- Set the SMTP server locale to English or match its exact prompt strings in the client.
- Include the challenge text (already in the error) in logs when diagnosing relay incompatibilities.
- Test SMTP auth against the actual production server, including localized configurations.
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)