semaphoreui/semaphore · error
Error generating key
Error message
Error generating key
What it means
Returned by the EnableTotp HTTP handler when the TOTP key generation library call (e.g. pquerna/otp) fails for the authenticated user. The server logs the underlying cause with the user_id and responds with HTTP 500 'Error generating key'. It means a TOTP secret could not be created for multi-factor enrollment, usually due to an invalid email/issuer combination or an internal crypto failure.
Solutions
- Check the server log line 'Failed to generate TOTP key' for the underlying error and user_id
- Verify the user's email field is non-empty and valid in the users table
- Re-run TOTP enablement after fixing the user record; if generation is flaky, retry the request
- Check the OTP library version for known issues with key generation options
Example fix
// before
Issuer: "Semaphore",
AccountName: user.Email,
// after
accountName := user.Email
if accountName == "" {
accountName = user.Username // or fail early with a 400
}
Issuer: "Semaphore",
AccountName: accountName, Defensive patterns
Strategy: validation
Validate before calling
if user == nil || strings.TrimSpace(user.Email) == "" {
return errors.New("user has no valid email for TOTP account name")
}
// then call the TOTP enable endpoint Type guard
func hasValidEmail(u *db.User) bool { return u != nil && strings.TrimSpace(u.Email) != "" } Prevention
- Ensure every user row has a non-empty email before enabling MFA
- Check server logs (user_id) for the underlying OTP library error on 500 responses
- Keep the OTP library up to date
- Add a pre-flight admin check that user records are complete after imports/syncs
When it happens
Trigger: POST to the user's TOTP enable endpoint when otp.Generate fails — e.g. the user.Email is empty/invalid as an account name, a nil/invalid random source, or an error returned by the TOTP generation options (Issuer 'Semaphore', AccountName user.Email).
Common situations: Database returned a user record with a malformed or empty email; a corrupted/random-source issue on the server; MFA enrollment attempted against an older user row lacking an email after a migration or LDAP sync.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Failed to link external account.
- OIDC sign-in failed: could not find or create the user…
- OIDC sign-in failed: invalid redirect URL.
- Internal Server Error
- err
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/6d9472174b3ca0e0.
Report an issue: GitHub.
Appendix: source
Thrown at api/users.go:421
if !util.Config.Mfa.Totp.Enabled {
helpers.WriteErrorStatus(w, "TOTP not enabled", http.StatusBadRequest)
return
}
if user.Totp != nil {
helpers.WriteErrorStatus(w, "TOTP already enabled", http.StatusBadRequest)
return
}
key, err := totp.Generate(totp.GenerateOpts{
Issuer: "Semaphore",
AccountName: user.Email,
})
if err != nil {
c.log.WithError(err).WithFields(log.Fields{"user_id": user.ID}).Error("Failed to generate TOTP key")
http.Error(w, "Error generating key", http.StatusInternalServerError)
return
}
var code, hash string
if util.Config.Mfa.Totp.AllowRecovery {
code, hash, err = util.GenerateRecoveryCode()
if err != nil {
helpers.WriteError(w, err)
return
}
}
newTotp, err := helpers.Store(r).AddTotpVerification(user.ID, key.URL(), hash)
if err != nil {
helpers.WriteError(w, err)
return
}View on GitHub (pinned to 1774ccb71a)