Tencent/WeKnora · warning

pending request already exists

Error message

pending request already exists

What it means

ErrPendingRequestExists is a package-level sentinel error indicating the tenant already has a pending request of the same type (join or role upgrade) with the organization. SubmitJoinRequest and RequestRoleUpgrade check via GetPendingRequestByTenantAndType and dedupe per-tenant: any user from that tenant triggers the rejection, not just the original requester.

Source

Thrown at internal/application/service/organization.go:622

	if org.OwnerTenantID == 0 {
		return true
	}
	return org.OwnerTenantID == tenantID
}

// generateInviteCode generates a random 16-character invite code
func generateInviteCode() string {
	bytes := make([]byte, 8)
	_, _ = rand.Read(bytes)
	return hex.EncodeToString(bytes)
}

// ----------------
// Join Requests
// ----------------

var (
	ErrPendingRequestExists    = errors.New("pending request already exists")
	ErrJoinRequestNotFound     = errors.New("join request not found")
	ErrCannotUpgradeToSameRole = errors.New("cannot request upgrade to same or lower role")
	ErrAlreadyAdmin            = errors.New("tenant is already an admin")
)

// SubmitJoinRequest submits a request for the caller's tenant to join an organization.
// Dedup is now per-tenant: any user from a tenant already with a pending join
// request is rejected (the same tenant can't queue two simultaneous joins).
func (s *organizationService) SubmitJoinRequest(ctx context.Context, orgID string, userID string, tenantID uint64, message string, requestedRole types.OrgMemberRole) (*types.OrganizationJoinRequest, error) {
	logger.Infof(ctx, "Tenant %d (rep user %s) submitting join request for organization %s", tenantID, userID, orgID)

	existing, err := s.orgRepo.GetPendingRequestByTenantAndType(ctx, orgID, tenantID, types.JoinRequestTypeJoin)
	if err == nil && existing != nil {
		return nil, ErrPendingRequestExists
	}

	org, err := s.orgRepo.GetByID(ctx, orgID)
	if err != nil {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Wait for an admin to review the existing pending request before submitting a new one.
  2. Check for a pending request first (query by org/tenant) and surface its status instead of re-submitting.
  3. Handle errors.Is(err, ErrPendingRequestExists) as an idempotent success in the UI.

Example fix

// before
req, err := svc.SubmitJoinRequest(ctx, orgID, userID, tenantID, msg, role)
if err != nil { return err }
// after
req, err := svc.SubmitJoinRequest(ctx, orgID, userID, tenantID, msg, role)
if errors.Is(err, organization.ErrPendingRequestExists) {
    return nil // already requested; treat as no-op
} else if err != nil { return err }
Defensive patterns

Strategy: try-catch

Validate before calling

// check first
existing, err := orgRepo.GetPendingRequestByTenantAndType(ctx, orgID, tenantID, reqType)
if err == nil && existing != nil { return fmt.Errorf("pending request %s already exists", existing.ID) }

Try / catch

if errors.Is(err, organization.ErrPendingRequestExists) {
    return nil // idempotent no-op
}

Prevention

When it happens

Trigger: Calling SubmitJoinRequest when the tenant already has a pending JoinRequestTypeJoin, or RequestRoleUpgrade when a pending JoinRequestTypeUpgrade exists for the same org/tenant pair.

Common situations: A user clicking 'request to join' twice, a different member of the same tenant submitting a duplicate request before an admin reviews the first, or retrying after a UI timeout without knowing the first call succeeded.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/2a2df9615f5ab835. Report an issue: GitHub.