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

  1. Check the server log line 'Failed to generate TOTP key' for the underlying error and user_id
  2. Verify the user's email field is non-empty and valid in the users table
  3. Re-run TOTP enablement after fixing the user record; if generation is flaky, retry the request
  4. 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

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


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)