gotify/server · warning

user does not exist and auto-registration is disabled

Error message

user does not exist and auto-registration is disabled

What it means

registerUser throws 403 'user does not exist and auto-registration is disabled' when an OIDC identity maps to no existing Gotify user and GOTIFY_OIDC_AUTOREGISTER is false. Gotify refuses to create the account, so login fails.

Source

Thrown at api/oidc.go:506

	}
	if user.OIDCID != nil {
		log.Warn().Str("oidc_id", oidcID).Str("bound_oidc_id", *user.OIDCID).Str("username", user.Name).Msg("OIDC login rejected: the username is already bound to a different OIDC identity")
		return nil, http.StatusForbidden, fmt.Errorf("the user %s is already bound to a different OIDC identity", user.Name)
	}
	user.OIDCID = &oidcID
	if len(a.GroupsAdmin) > 0 {
		user.Admin = hasAdminGroup
	}
	if err := a.DB.UpdateUser(user); err != nil {
		return nil, http.StatusInternalServerError, fmt.Errorf("failed to bind user to OIDC identity: %w", err)
	}
	log.Warn().Str("oidc_id", oidcID).Str("username", user.Name).Bool("admin", user.Admin).Msg("OIDC link by username")
	return user, 0, nil
}

func (a *OIDCAPI) registerUser(username, oidcID string, hasAdminGroup bool) (*model.User, int, error) {
	if !a.AutoRegister {
		return nil, http.StatusForbidden, errors.New("user does not exist and auto-registration is disabled")
	}
	user := &model.User{
		Name:   username,
		Pass:   nil,
		OIDCID: &oidcID,
	}

	if len(a.GroupsAdmin) > 0 {
		user.Admin = hasAdminGroup
	}

	if err := a.DB.CreateUser(user); err != nil {
		return nil, http.StatusInternalServerError, fmt.Errorf("failed to create user: %w", err)
	}
	log.Info().Str("oidc_id", oidcID).Str("username", user.Name).Bool("admin", user.Admin).Msg("OIDC auto registration")
	if err := a.UserChangeNotifier.fireUserAdded(user.ID); err != nil {
		log.Error().Err(err).Uint("user_id", user.ID).Msg("Could not notify user change")
	}

View on GitHub (pinned to 14bfc25627)

Solutions

  1. Create the user in Gotify in advance with the matching username (and link-by-username enabled) so the identity binds on first login.
  2. Set GOTIFY_OIDC_AUTOREGISTER=true if auto-creating accounts is acceptable.
  3. Have an admin provision the account, then have the user log in again.
  4. Verify GOTIFY_OIDC_LINK_BY_USERNAME settings if you expect an existing account to be matched.

Example fix

// before
GOTIFY_OIDC_AUTOREGISTER=false // new IdP user blocked
// after
GOTIFY_OIDC_AUTOREGISTER=true
// or: create the user in Gotify first, then log in
Defensive patterns

Strategy: fallback

Validate before calling

if (!process.env.GOTIFY_OIDC_AUTOREGISTER) {
  const exists = await userExistsByUsername(claims.preferred_username);
  if (!exists) console.warn('user will be rejected; provision account or enable GOTIFY_OIDC_AUTOREGISTER');
}

Try / catch

try {
  await oidcLogin();
} catch (e) {
  if (e.response?.status === 403 && /auto-registration is disabled/.test(e.response.data)) {
    await provisionUser(username); // admin API/manual step, then retry login once
  } else throw e;
}

Prevention

When it happens

Trigger: First login of a new IdP user when auto-registration is disabled and no existing user matches by OIDC ID or (if link-by-username enabled) by username.

Common situations: Fresh Gotify deployment with OIDC enabled but AUTOREGISTER unset; new employee logging in before an admin created their Gotify account; provider tenant change causing usernames not to match existing accounts.

Related errors


AI-assisted analysis of gotify/server@14bfc25627 (2026-09-05). Data as JSON: /api/errors/03d41a2e4b90b301. Report an issue: GitHub.